home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / hashsig / hashsig.lha / signCheck1.0.c < prev    next >
Text File  |  1993-08-09  |  130KB  |  4,146 lines

  1. /*
  2.    This is an experimental implementation of the signing and checking
  3.    algorithms for a digital signature based on one-way hash functions. The
  4.    new signature method is, for this reason, called a "hash signature." Many
  5.    methods of generating a digital signature from a one-way hash function are
  6.    feasible, so to distinguish this particular method it is called the
  7.    "Xerox Hash Signature."  The Xerox Hash Signature presently includes
  8.    three separate components:
  9.  
  10.      1.)  The Abstract Xerox Hash Signature.  This includes the software
  11.           which defines how to use a one-way hash function to generate
  12.           a digital signature, but excludes the software of any particular
  13.           one way hash function.  In this implementation, the Abstract
  14.           Xerox Hash Signature specifically excludes both MD4 and Snefru.
  15.           The Abstract Xerox Hash Signature specifies how to generate
  16.           a digital signature given a one-way hash function, but does
  17.           NOT specify any particular signature system, nor any particular
  18.           one-way hash function.
  19.  
  20.      2.)  The one-way hash function Snefru (4 passes).
  21.  
  22.      3.)  The one-way hash function MD4.
  23.  
  24. *    Addendum dated 91.11.13:  since the original implementation of this
  25. *    system, MD5 has been made available and MD4 is no longer recommended.
  26. *    Further, Snefru with 8 passes has been made available, and Snefru
  27. *    with 4 passes is no longer recommended.  For these and various other
  28. *    reasons, the present system should be viewed as a experimental, and
  29. *    is not intended for production use.
  30.  
  31.    It is convenient to have a name for the combination of these components.
  32.    In general, the term "Xerox Hash Signature" refers to one or more specific
  33.    digital signatures generated by combining the Abstract Xerox Hash Signature
  34.    with one or more specific one-way hash functions. In this particular case,
  35.    the Xerox Hash Signature refers to the coupling of the Abstract Xerox Hash
  36.    Signature with the particular one-way hash functions Snefru or MD4.
  37.  
  38.    In other contexts, the term "Xerox Hash Signature" could be used to
  39.    describe the coupling of the Abstract Xerox Hash Signature with other
  40.    specific one-way hash functions. When it is necessary to discuss a
  41.    specific digital signature method created by coupling the Abstract Xerox
  42.    Hash Signature with some specific one-way hash function, the combination
  43.    can use the name "The Xerox Hash Signature based on <name of one-way hash 
  44.    function>."  For example, the present software can be specifically described
  45.    as the Xerox Hash Signature based on Snefru or MD4.
  46.  
  47.    In general, the signature system described by the term "The Xerox Hash
  48.    Signature" will be determined by context.  The term "The Abstract Xerox
  49.    Hash Signature" refers specifically to the general method of combining
  50.    an arbitrary one-way hash function into a digital signature system, but
  51.    does not include any particular one-way hash function nor does it define
  52.    or specify any particular implementation of a digital signature.  Only
  53.    when the Abstract Xerox Hash Signature is combined with some specific one
  54.    way hash function have we defined a particular digital signature.
  55.  
  56.    Both Snefru and MD4 are available separately.  Both Snefru and MD4 are
  57.    accompanied by separate notices.  The implementations of Snefru and MD4
  58.    included here have been modified for convenient use with the present
  59.    software, but they are distinct entities.  The notices which accompany
  60.    Snefru and MD4 have been reproduced in the appropriate files.  Those
  61.    notices do not pertain to the Abstract Xerox Hash Signature, which
  62.    is a separate and distinct software entity and which is covered by
  63.    separate and distinct notices, which follow:
  64.  
  65. **************************************************************************
  66.    COPYRIGHT (C) 1990 Xerox corporation.  All rights reserved.
  67.  
  68.    XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE
  69.    MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE FOR
  70.    ANY PARTICULAR PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED
  71.    WARRANTY OF ANY KIND.
  72.  
  73.    This software is being made available for experimental use only.  No
  74.    right is granted to use this software for any other purpose.  The rights
  75.    (if any) granted for using the individual modules of this software are
  76.    specified by notices appearing in those modules.
  77.  
  78.    Further, in the author's opinion, it is very possible that one or more
  79.    security related bugs exist in this experimental implementation.
  80.    Also note that the routine OpenAndLockTwoFiles has been modified
  81.    to improve portability, but this has created a timing window.
  82.    This should not significantly affect experimental use.
  83.  
  84.    This software may be covered by one or more claims of either or
  85.    both of the following patents:
  86.  
  87.    #4,881,264:
  88.    Digital Signature System and Method
  89.        Based on a Conventional Encryption Function
  90.    Issued:        November 14, 1989.
  91.    Inventor:        Ralph C. Merkle.
  92.    Patent owned by:    Ralph C. Merkle.
  93.    Contact:        Ralph C. Merkle
  94.             Xerox PARC
  95.             3333 Coyote Hill Road
  96.             Palo Alto, CA 94304
  97.             merkle@xerox.com
  98.  
  99.    #4,309,569:
  100.    Method of Providing Digital Signatures
  101.    Issued:        January 5, 1982.
  102.    Inventor:        Ralph C. Merkle.
  103.    Patent owned by:    Stanford University.
  104.    Contact:        Joe Koepnick
  105.             Stanford University
  106.             Office of Technology Licensing
  107.             857 Serra Street, Second Floor
  108.             Stanford, CA 94305-6225.
  109.             koepnick@angelo.Stanford.EDU
  110.  
  111.    XEROX MAKES NO REPRESENTATION WHATSOEVER WITH RESPECT TO THE RELEVANCE
  112.    OF SUCH PATENTS TO THIS SOFTWARE OR WITH RESPECT TO THE VALIDITY OF
  113.    THESE PATENTS.  XEROX AUTHORIZES NO USES OF THE ABSTRACT XEROX HASH
  114.    SIGNATURE EXCEPT FOR THOSE THAT ARE STRICTLY LIMITED TO EXPERIMENTAL
  115.    PURPOSES.
  116.  
  117.    These notices must be retained in any copies of any part of this software.
  118. **************************************************************************
  119.  
  120.    The following papers describe some of the concepts and ideas used in
  121.    this program:
  122.  
  123.    "A Certified Digital Signature" by Ralph C. Merkle, Crypto '89.
  124.    "One Way Hash Functions and DES" by Ralph C. Merkle, Crypto '89.
  125.    "A Fast Software One Way Hash Function" by Ralph C. Merkle, accepted by
  126.         The Journal of Cryptology.
  127.    "A Digital Signature Based On A Conventional Encryption Function" by
  128.         Ralph C. Merkle, Crypto '87.
  129.    "Secrecy, Authentication, and Public Key Systems" by Ralph C. Merkle,
  130.         Ph.D. Thesis, Stanford University Electrical Engineering Dept. 1979.
  131.    "Design Principles for Hash Functions" by Ivan Bjerre Damgard, Crypto '89.
  132.    "Constructing Digital Signatures from a One Way Function" by
  133.         Leslie Lamport, Computer Science Laboratory Technical Report
  134.         October 18, 1979, CSL-98
  135.  
  136.    This is version 1.0d, June 19, 1990.
  137.  
  138.    THE SIGNING ALGORITHM
  139.  
  140.    The signing algorithm accepts, as input,
  141.    
  142.    1.)  An input file <input> to be signed, and an optional short
  143.    ascii "message" that accompanies the signed file.
  144.  
  145.    2.)  The "current auxilliary information" (a file) which keeps track
  146.    of various bookkeeping information.  The file is not secret, and
  147.    the information in it can be divulged without compromising the
  148.    security of the signature. Loss or destruction of the aux info file
  149.    is not a catastrophe -- the information in it can be re-computed from
  150.    the machine key file and the secret user key using the "recoverauxinfo"
  151.    command.
  152.    
  153.    3.)  A "user key" entered by the user.  The user
  154.    key is not retained by the program after the message has been signed.
  155.  
  156.    4.)  A "machine key" file that holds a "machine key" and the
  157.    authentication path.  If the "machine key" is compromised, then
  158.    the security of the system rests solely on the user key.  If the
  159.    user key is compromised, then the security of the system rests
  160.    solely on the machine key.  Both keys together are required to
  161.    generate the "secret key" that is actually used to sign messages.
  162.  
  163.    The use of two separate keys has two distinct purposes:
  164.      (a) It means that guessing the user key (which is often ill-chosen
  165.          by an unsophisticated or disinterested user) will not compromise
  166.          the machine key or the secret key, thus improving security, and
  167.      (b) It insures that the user will not use the same secret key
  168.          to generate a new secret-key/public-key pair.  Generating the
  169.          same secret-key/public-key pair and signing two sets of
  170.          messages with it will seriously compromise security.
  171.  
  172.    The "machine key" file must also be resistant to unauthorized
  173.    modification -- unauthorized changes to the "authentication path"
  174.    specified in this file can compromise security.  In most applications,
  175.    it would also be advisable to make the "machine key" unreadable
  176.    by anyone other than those properly authorized.
  177.    
  178.    The signing algorithm produces as output:
  179.    
  180.    1.)  A "signature file."  This file is normally .JZ<input file>,
  181.    (e.g., the input file name prefixed with ".JZ").
  182.  
  183.    THE CHECKING ALGORITHM
  184.  
  185.    The checking algorithm re-computes the public key from the signature
  186.    and the signed file.  The signed file and message are first hashed
  187.    using a one-way hash function (Snefru 2.0 or MD4, other algorithms
  188.    can be added easily) to 128 bits.  This 128-bit hash value is
  189.    then further hashed to 64-bits using a parameterized one-way hash
  190.    function.  This 64-bit value is then hashed to compute the
  191.    public key.  The public key is then looked up in a public
  192.    directory to determine the signer.  If no matching public key
  193.    is found in the public directory, the signer is unknown.
  194.  
  195.    Note that re-computing the public key is idiosyncratic to hash
  196.    signatures.  Other signature methods do not re-compute the
  197.    public key, but instead require that the public key be entered
  198.    as a parameter to the signature checking algorithm.  This
  199.    difference might be confusing for those familiar with the
  200.    normal methods of checking a signature.
  201.    
  202.    Input for the checking algorithm is:
  203.    
  204.    1.)  An input file <input> whose signature is to be checked.
  205.  
  206.    2.)  The signature file, .JZ<input>.
  207.  
  208.    Output from the checking algorithm is:
  209.  
  210.    1.)  The re-computed public key.
  211.  
  212.  
  213.    The re-computed public key is used to find any matching
  214.    (previously authenticated) public keys present in the public directory.
  215.    If such a match is found, then the program prints out the name
  216.    of the signer and other information taken from the signed message
  217.    and the public entry.  If no known public key matches the
  218.    re-computed public key, then a diagnostic is issued.
  219.  
  220.    Clearly, the correctness of the result depends on the validity of
  221.    the entries in the public directory.  Various methods of
  222.    safeguarding the public entries have been proposed in the
  223.    literature.  A consideration of these methods is beyond the scope
  224.    of these comments.
  225.  
  226.    In general, the security of hash signatures is dependent on the security of
  227.    the underlieing one-way hash function. If that one-way hash function is
  228.    secure, then the signature method is secure.  Two one-way hash functions
  229.    suitable for use in this hash signature are:  Snefru 2.0 (with 4 passes)
  230.    and MD4.  Other one-way hash functions can be easily added to the code.
  231.    The selection of which one way-hash function to use can be based on any of
  232.    several criteria, including performance, perceived security, availability,
  233.    etc.
  234.    
  235.    Snefru 2.0 is available via anonymous FTP from arisia.xerox.com in directory
  236.    /pub/hash.   (MD4 is also available in the same directory as a courtesy).
  237.  
  238.    MD4 has not yet received adequate review to establish its security.
  239.    Its security should therefore be viewed with caution at the
  240.    present time (90.04.25).
  241.  
  242. Further information about MD4 is available from:
  243.     RSA Data Security.
  244.     10 Twin Dolphin Drive
  245.     Redwood City, CA 94065
  246.     415-595-8782
  247.     rsa@well.uucp
  248.  
  249. Either Snefru or MD4 can be
  250. used in the current hash signature method by setting the "hashMethod"
  251. variable appropriately.  Snefru is set to 4 passes.  Setting Snefru
  252. to 2 passes is known to be insecure (courtesy of the work of Eli Biham).
  253. This is available by setting the "hashMethod" variable to SNEFRU4_METHOD.
  254. MD4 can be specified by setting "hashMethod" to MD4_METHOD.
  255.  
  256. Snefru with 2 passes can be broken.  The security of Snefru with 4 passes
  257. has not yet received adequate analysis and its use must be viewed with
  258. caution at the present time (90.04.25).
  259.  
  260. *  Addendum added 91.11.13:  Snefru with 8 passes and MD5 are both
  261. *  available.  For these and other reasons, the present software
  262. *  should be viewed as experimental.  Use of the present system
  263. *  for production use is not recommended.
  264.  
  265. Please note that the constant values that specify different hash
  266. methods must be unique.  For this reason, anyone who wishes to add
  267. a new method should contact Ralph C. Merkle to insure that the
  268. constant value selected does not conflict with other values.  In
  269. any event, constants below 100 (decimal) are reserved for use by
  270. Xerox.
  271.  
  272. Other one - way hash functions are known.  DES-based one-way
  273. hash functions could be used, but the inclusion of DES source
  274. code here might create export issues.  DES-based one way hash
  275. functions are significantly slower than the two functions
  276. specifically designed for software implementation, Snefru and MD4;
  277. on the other hand it is reasonable to place greater confidence
  278. in the security of the recent IBM proposal based on DES.
  279. (Note that the security of other DES-based one-way hash
  280. functions should be viewed with great caution).  Other one-way hash
  281. functions known to the author at this time are either significantly
  282. less efficient or are still subject to serious reservations about
  283. security.
  284.  
  285. *  Addendum added 91.11.13:  it is expected that NIST will soon
  286. *  adopt a one way hash function.  This hash function could be
  287. *  adopted as the basis for the hash signature, in which case the
  288. *  security of the system would depend on the security of the NIST
  289. *  provided one-way hash function (modulo the fact that it is likely
  290. *  that some security-related bugs exist in this implementation).
  291.  
  292. The two values "securitySize" and "parameterSize"
  293. directly control the security that is provided by the hash
  294. signature.  "securitySize" is the number of 32 - bit words that
  295. are used to hold security-critical values.  "parameterSize" is
  296. the number of 32-bit words used to hold the security-related
  297. "parameter" values.  It is expected that securitySize will
  298. either be  2 (providing 64 bits of effective security) or 3
  299. (providing 96 bits of effective security).  The value of
  300. parameterSize will usually be 2 (providing 2 ** 64 possible parameters).
  301. Note that "parameters" to the one-way hash function need not be
  302. randomly selected from a large space.  However, different applications
  303. of the one-way hash function should normally use different values
  304. for the parameter.  Thus, parameter values might start at 1 and proceed
  305. systematically through 2, 3, 4, etc.  Accidental re-use of the same
  306. parameter value has only a minor impact on security, but widespread
  307. re-use of the same parameter value would substantially reduce security.
  308.  
  309. Setting both securitySize and parameterSize to 2 (64 bits) should
  310. provide a level of security sufficient for most commercial
  311. applications.  For applications requiring a higher level of security,
  312. securitySize can be increased.  In most applications, even at
  313. a very high security level, it will not be necessary to increase
  314. parameterSize.  The security of the one-way hash functions is also
  315. extremely important.  At this point in time, both Snefru 2.0 and MD4
  316. are receiving widespread scrutiny.  It is too early to make reliable
  317. statements about the level of security that they provide.
  318.  
  319. Note:  Snefru 2.0 with 2 passes was broken by Eli Biham, a PhD student of
  320. Adi Shamir's.  As a consequence, the use of 2 passes is not recommended.
  321. It would seem prudent to use 4 passes at the time of this writing
  322. (90.04.25).
  323.  
  324. Further note:  Although it is in general possible to prove that
  325. hash signatures are secure if the underlieing one-way hash function
  326. is secure, it should be remembered that the present program has
  327. some 6,000 lines of code in it.  The present code has not been reviewed
  328. by anyone other than the author, nor does the author make any claims
  329. of infallibility.  It is therefore probable that some security related
  330. bugs exist in the present implementation.  This implementation should
  331. be verified or re-implemented independently prior to any non-experimental
  332. use.
  333.  
  334. If anyone using this program finds a bug or error, please contact
  335. Ralph C.Merkle via E-mail (merkle@xerox.com) or
  336. via normal mail at:
  337.  
  338.         Xerox PARC
  339.         3333 Coyote Hill Road
  340.         Palo Alto, CA 94304
  341.         (415) 494-4000
  342.  
  343.  
  344.  
  345. A signature (the contents of the ".sig" file) has the following
  346. data structure:
  347.  
  348. bits    description
  349.     
  350.     word 0
  351. 16    hashMethod.  Uniquely identifies the particular method used.
  352. 4        Reserved for future use -- set to 0 for now
  353. 4    securitySize (in 32-bit words)
  354. 4    parameterSize (in 32-bit words)
  355. 4    bitsPerVerifier
  356.  
  357.     word 1
  358. 16    total number of words (in the signature itself) to be hashed
  359. 8    number of words of binary data (excluding the ascii message)
  360. 8    number of OTTs (One Time Trees) in this signature
  361.  
  362.     word 2
  363. 32    The date and time the message was signed, in seconds since
  364.     00:00:00 GMT,  Jan.  1,  1970.  (Standard UNIX time format).
  365.  
  366.     word 3
  367. 128    hash value of file being signed.  Can occupy more than 4 words
  368.         depending on the value of "securitySize".
  369.  
  370.     word 7
  371. 64    initial parameter.  Can occupy more than 2 words depending on the
  372.         value of "parameterSize".
  373.  
  374.     word 9
  375. 0    Additional binary data.  Can occupy more than 0 words depending
  376.         on the value in the "number of words of binary data" field
  377.         (see above).
  378.  
  379.     word 9
  380. 0    An ascii text message to be associated with the signature.  Can
  381.         occupy more than 0 words depending on the "total number of words"
  382.         field (see above).
  383.  
  384.     Further 32-bit words:
  385.   Repeat the following block according to the
  386.   8-bit "number of OTTs" (One Time Trees) parameter.
  387.  
  388. 64    count verifier   (size varies according to "securitySize")
  389. 64    count verifier
  390.     .
  391.     . repeated 2**bitsPerVerifier times
  392.     .
  393. 64    count verifier
  394. 32    path description (Fixed at 32 bits for all time)
  395. 64    branch verifier  (size varies according to "securitySize")
  396. 64    branch verifier
  397. 64    branch verifier
  398.    .
  399.    .  repeated according to "path description" (up to 31 times)
  400.    .
  401. 64    branch verifier
  402. 64    branch verifier
  403.  
  404.    End of repeated block
  405.  
  406.  
  407.    Both the count verifiers and the branch verifiers given above can be
  408.    increased in size in increments of 32 bits.  When securitySize is
  409.    2 they will be 64 bits (as shown); when securitySize is 3 they
  410.    would be 96 bits, when securitySize is 4 they would be 128 bits,
  411.    etc.
  412.    
  413.    The 64-bit initial parameter can be increased in size in increments
  414.    of 32 bits by increasing the parameterSize from 2.  Thus, when
  415.    parameterSize is 2 the initial parameter will be 64 bits (as
  416.    shown).  When the parameterSize is 3, the initial parameter will
  417.    be 96 bits.  When the parameterSize is 4, the initial parameter
  418.    will be 128 bits.
  419.    
  420.    The path description will always be 32 bits.
  421.    
  422.    
  423.    Note that "word32" MUST be 32 bits
  424.    
  425.    Inventor, designer, and implementor:  Ralph C. Merkle
  426.    
  427. */
  428.  
  429. #include <stdio.h>
  430. #include <string.h>
  431. #include <sys/time.h>
  432. #include <fcntl.h>
  433. #include <sys/types.h>
  434. #include <sys/stat.h>
  435. #include <pwd.h>
  436. #include "md4.h"
  437. #include "wellKnownDirectories"
  438.  
  439.     /* security related parameters */
  440. #define MAX_PARAMETER_SIZE 4
  441. #define MAX_SECURITY_SIZE 4
  442. #define MAX_PUBLIC_KEY_SIZE (1+MAX_PARAMETER_SIZE+MAX_SECURITY_SIZE)
  443. #define MACHINE_KEY_SIZE 4
  444. #define USER_KEY_SIZE  8
  445. #define USER_KEY_SIZE_IN_BYTES (4*USER_KEY_SIZE)
  446. #define SECRET_KEY_SIZE 4
  447. #define HASHED_USER_KEY_SIZE 2
  448. #define WORD_SIZE_IN_BITS 32
  449. #define MAX_HASH_VALUE_SIZE (2*MAX_SECURITY_SIZE)
  450.  
  451. /*
  452.  * Hash method constants.
  453.  * Note:  DO NOT add an additional hash method constant without
  454.  * contacting Xerox.  These constants must be globally
  455.  * unique.  Values less than 100 are reserved by Xerox and
  456.  * should not be used by others.
  457.  */
  458. #define MD4_METHOD 100
  459. #define SNEFRU4_METHOD 4
  460.  
  461.     /*  other parameters and constants */
  462. #define MAX_OTT_SIZE 128 
  463. #define MAX_BITS_PER_VERIFIER 10
  464. #define TRUE 1
  465. #define FALSE 0
  466. #define SIGN 1
  467. #define CHECK 0
  468. #define COMPUTE_OTT_HASH 2
  469. #define PATHOVERFLOW 1
  470. #define NOPATHOVERFLOW 0
  471. #define DO_NOT_CREATE_FILE 1
  472. #define CREATE_FILE 0
  473. #define MAX_INPUT_BLOCK_SIZE 16
  474. #define SNEFRU_INPUT_BLOCK_SIZE 16
  475. #define INPUT_BLOCK_SIZE 16
  476. #define MAX_SIGNATURE_SIZE 4096
  477. #define MAX_FILE_NAME_SIZE_IN_BYTES 100
  478. /* warning!  If you change MAX_USER_NAME_SIZE_IN_BYTES,
  479.  * scan through the source for all occurences --
  480.  * some occurences are in quotes and so cannot
  481.  * be expanded by the pre-processor (and
  482.  * just have the integer value 300...)
  483.  */
  484. #define MAX_USER_NAME_SIZE_IN_BYTES 300
  485. #define MAX_LINE_LENGTH 1000
  486. #define MAX_NO_OF_COUNTS 50
  487. #define MAX_STACK_DEPTH 10
  488. #define MAX_MESSAGE_SIZE 512
  489. #define MAX_MESSAGE_SIZE_IN_BYTES (MAX_MESSAGE_SIZE*4)
  490. #define DEBUG 0
  491. #define SELF_TEST 0
  492. #define SHOW_TIMES 0
  493. #define SHORT_UNUSUAL_STRING "JZ"
  494. #define MIN_DEPTH 1
  495. #define WIPE_IT 4096
  496. #define VERSION "@(#) Hash Signatures Version 1.0d June 19, 1990"
  497.  
  498. typedef unsigned long int word32;
  499.  
  500.     struct SIG_BUF {
  501.         word32 signature[MAX_SIGNATURE_SIZE];
  502.         int     locInSignature;
  503.     };
  504.  
  505. void HashExpand();
  506. void HashAny();
  507. void DoSelfTest();
  508. void Snefru512();
  509. long clock();
  510. long time();
  511. char *sprintf();
  512. void SnefruHashFile();
  513.  
  514. #if DEBUG
  515. void 
  516. PrintIt (string, val, length)
  517.     char   *string;
  518.     word32 val[];
  519.     int     length;
  520. {    int     di;
  521.     printf ("%s", string);
  522.     for (di = 0; di < length; di++)
  523.         printf (" %lx", val[di]);
  524.     printf ("\n");
  525. }
  526. #endif
  527.  
  528. /*
  529.  * Compute the number of bits required to represent the given value
  530.  */
  531. int 
  532. SizeInBits (value)
  533.     word32 value;
  534. {    int     i;
  535.  
  536.     for (i = 0; i < WORD_SIZE_IN_BITS; i++)
  537.         if ((value >> i) == 0)
  538.             return (i);
  539.     return (WORD_SIZE_IN_BITS);
  540. }
  541.  
  542.  
  543. /*
  544.  * Copy an input array to an output array of "size" words. The following
  545.  * routine can be replaced with "memcpy" if this is defined in your
  546.  * implementation.
  547.  */
  548. void 
  549. Copy (out, in, size)
  550.     word32 in[];
  551.     word32 out[];
  552.     int     size;
  553. {    int     i;
  554.     for (i = 0; i < size; i++)
  555.         out[i] = in[i];
  556. }
  557.  
  558. /*
  559.  * The following routine is a simple error exit routine  -- it prints a
  560.  * message and aborts
  561.  */
  562. void 
  563. ErrAbort (s)
  564.     char   *s;
  565. {    /*  Don't print empty strings */
  566.     if (s[0] != (char) 0)
  567.         fprintf (stderr, "%s\n", s);
  568.     exit (2);
  569. };
  570.  
  571. /*
  572.  * PORTABILITY WARNING:  The following routine should port
  573.  * to most Unix systems.  It returns the GMT time in seconds since
  574.  * January 1, 1970.
  575.  */
  576. long
  577. GetTime32()
  578. {    time_t temp[1];
  579.  
  580.     (void) time(temp);
  581.     return(temp[0]);
  582. }
  583.  
  584. #if SHOW_TIMES
  585. /*
  586.  * PORTABILITY WARNING:  The following routine should port to
  587.  * most Unix systems. It returns the cpu time in microseconds.
  588.  */
  589. word32
  590. GetCpuTime()
  591. {
  592.     return(clock());
  593. }
  594. #endif
  595.  
  596.  
  597. /* PORTABILITY WARNING: The following routine should
  598.  * be moderately portable among Unix systems.
  599.  * It is intended to create a new
  600.  * file and set the access modes for that file to
  601.  * READ and WRITE by the creator of the file, but
  602.  * to disallow any access (read, write, or anything else)
  603.  * by others.  It returns a stream that will
  604.  * be used to write information to the created file.
  605.  *
  606.  * If the file already exists, this routine will check
  607.  * to see if it's "empty".  By definition, an "empty"
  608.  * file has 4 bytes of "0" at its beginning (or a length
  609.  * of less than 4 bytes).  If the file is empty, the stream
  610.  * is returned.  If the file is not empty, a diagnostic
  611.  * is issued.
  612.  *
  613.  */
  614. FILE *
  615. OpenIfEmpty(fileName)
  616. char *fileName;
  617. {    int    fd;
  618.     FILE    *stream;
  619.     char    temp[4];
  620.     int    length;
  621.     int    i;
  622.  
  623.     fd = open(fileName, O_WRONLY | O_CREAT | O_EXCL, 0600);
  624.     stream = fdopen(fd, "w");
  625.     if (stream == NULL){
  626.         stream = fopen(fileName, "r+");
  627.         if (stream == NULL) {
  628.             fprintf(stderr, "Can't read from \"%s\"\n", fileName);
  629.             ErrAbort("");
  630.         };
  631.         length = fread(temp, 1, 4, stream);
  632.         if (ferror(stream) != 0) {
  633.             fprintf(stderr, "Can't access \"%s\"\n", fileName);
  634.             ErrAbort("");
  635.         };
  636.         for (i=0; i<length; i++)
  637.             if (temp[i] != 0) {
  638.                 fprintf(stderr, "File \"%s\" is not empty\n",
  639.                     fileName);
  640.                 ErrAbort(
  641.                 "To destroy old key, use \"destroyoldkey\"");
  642.             };
  643.         fseek(stream, 0L, 0);
  644.     };
  645.     return(stream);
  646. }
  647.  
  648. /* PORTABILITY WARNING: THE FOLLOWING ROUTINE IS NOT VERY PORTABLE.
  649.  * The following routine is intended to open and lock two files.
  650.  * This will prevent two versions of the current program
  651.  * from simultaneously attempting to update stable storage.
  652.  *
  653.  * For experimental purposes, the locking features of this routine
  654.  * can simply be deleted (e.g., the calls to fcntl can be removed).
  655.  * It should be remembered that THIS WILL PRODUCE A TIMING WINDOW
  656.  * WHICH CAN RESULT IN LOSS OF SECURITY IF TWO PROGRAMS ATTEMPT
  657.  * TO SIGN A MESSAGE WITH THE SAME SIGNING KEY AT THE SAME TIME.
  658.  */
  659. void
  660. OpenAndLockTwoFiles(s1Ptr, s1Name, s2Ptr, s2Name)
  661.     FILE    **s1Ptr;
  662.     char    *s1Name;
  663.     FILE    **s2Ptr;
  664.     char    *s2Name;
  665. {    int    fd1;
  666.     int    fd2;
  667.     struct flock localLock;
  668.  
  669.     *s1Ptr = fopen(s1Name, "r+");
  670.     *s2Ptr = fopen(s2Name, "r+");
  671.     if (*s1Ptr == NULL) {
  672.         fprintf(stderr, "Can't open \"%s\"\n", s1Name);
  673.         ErrAbort("");
  674.     };
  675.     if (*s2Ptr == NULL) {
  676.         fprintf(stderr, "Can't open \"%s\"\n", s2Name);
  677.         ErrAbort("");
  678.     };
  679.     fd1 = fileno(*s1Ptr);
  680.     fd2 = fileno(*s2Ptr);
  681.     localLock.l_type = F_WRLCK;
  682.     localLock.l_whence = 0;
  683.     localLock.l_start = 0;
  684.     localLock.l_len = 0;
  685. /*  WARNING:  REMOVAL OF THE FOLLOWING TWO STATEMENTS CREATES
  686.  *  A TIMEING WINDOW.  THIS SHOULD NOT MATTER FOR EXPERIMENTAL
  687.  *  USAGE, BUT SHOULD NOT BE ALLOWED IN A PRODUCTION VERSION
  688.  */
  689. /*
  690.     if (fcntl(fd1, F_SETLKW, (int) &localLock) == -1) {
  691.         fprintf(stderr, "Can't lock \"%s\"\n", s1Name);
  692.         ErrAbort("");
  693.     };
  694.     if (fcntl(fd2, F_SETLKW, (int) &localLock) == -1) {
  695.         fprintf(stderr, "Can't lock \"%s\"\n", s2Name);
  696.         ErrAbort("");
  697.     };
  698.  */
  699. }
  700.  
  701.  
  702. /*
  703.  * The following routine closes a file.  If there are problems
  704.  * with the close, it prints an error message and calls ErrAbort.
  705.  */
  706. void
  707. FileClose(stream, streamName)
  708.     FILE    *stream;
  709.     char    *streamName;
  710. {
  711.     if (fclose(stream) != 0) {
  712.         fprintf(stderr, "Can't fclose \"%s\"\n", streamName);
  713.         ErrAbort("");
  714.     };
  715. }
  716.  
  717.  
  718. /* PORTABILITY WARNING.  THIS ROUTINE IS NOT VERY PORTABLE.
  719.  * The following routine is intended to "sync" a file and then
  720.  * close it, e.g., make sure the file is actually written to disk.
  721.  * The routine fflush will do this on some systems (though
  722.  * not all).  The routine fsync will do this, but is
  723.  * not widely portable.  The exact method of implementing
  724.  * FileSyncAndClose will vary from system to system.
  725.  *
  726.  * Note that FileSyncAndClose is presumed to "unlock" the file
  727.  * as well as closing it.
  728.  */
  729. void
  730. FileSyncAndClose(stream, streamName)
  731.     FILE    *stream;
  732.     char    *streamName;
  733. {    int    fd;
  734.  
  735.     if (fflush(stream) != 0) {
  736.         fprintf(stderr, "Can't fflush \"%s\"\n", streamName);
  737.         ErrAbort("");
  738.     };
  739.     fd = fileno(stream);
  740.     if (fsync(fd) != 0) {
  741.         fprintf(stderr, "Can't fsync \"%s\"\n", streamName);
  742.         ErrAbort("");
  743.     };
  744.     FileClose (stream, streamName);
  745. }
  746.  
  747. /*
  748.  * PORTABILITY WARNING:  The following routine is not very
  749.  * portable, although it should work on most Unix systems.
  750.  *
  751.  * It returns 0 if the file exists, non-zero otherwise
  752.  */
  753. int
  754. FileExists(fileName)
  755.     char    *fileName;
  756. {    struct stat buf[1];
  757.  
  758.     return(stat(fileName, buf));
  759. }
  760.  
  761. /*
  762.  * PORTABILITY WARNING:  The following routine is not very
  763.  * portable, although it should work on most Unix systems.
  764.  *
  765.  * It returns 0 if the file exists and has a non-zero length
  766.  */
  767. int
  768. SignatureExists(fileName)
  769.     char    *fileName;
  770. {    struct stat buf[1];
  771.  
  772.     if (stat(fileName, buf) != 0)
  773.         return(-1);
  774.     if (buf->st_size == 0)
  775.         return(-1);
  776.     return(0);
  777. }
  778.  
  779.  
  780. /*
  781.  * PORTABILITY WARNING:  The following routine is not very
  782.  * portable, although it should work on most Unix systems.
  783.  *
  784.  * Returns the name of the owner of the file
  785.  */
  786. char *
  787. FileOwnersName(file)
  788.     FILE    *file;
  789. {    struct passwd    temp[1];
  790.     struct stat    buf[1];
  791.     static    char    ownersName[MAX_USER_NAME_SIZE_IN_BYTES];
  792.  
  793.     if (fstat(fileno(file), buf) != 0)
  794.         ErrAbort("Bad fstat");
  795.     *temp = *getpwuid(buf->st_uid);
  796.     strcpy(ownersName, temp->pw_name);
  797.     return(ownersName);
  798. }
  799.  
  800.  
  801. /*
  802.  * PORTABILITY WARNING:  The following routine is not very
  803.  * portable, although it should work on most Unix systems.
  804.  *
  805.  * The following routine is intended to determine the user's
  806.  * name.  This name will then be used as the file name which
  807.  * holds the user's "stable storage" (machine key and stuff).
  808.  * The most important thing to remember about this routine is
  809.  * that THE TWO USER NAMES FOR TWO DIFFERENT USERS MUST BE
  810.  * DIFFERENT.  If not, there will be a collision in the file
  811.  * name space, with resulting chaos and confusion.
  812.  */
  813. void
  814. GetUserName(userName)
  815.     char    userName[MAX_USER_NAME_SIZE_IN_BYTES];
  816. {    struct passwd    temp[1];
  817.  
  818.     *temp = *getpwuid(getuid());
  819.     if (strlen(temp->pw_name) >= MAX_USER_NAME_SIZE_IN_BYTES) {
  820.         fprintf(stderr, "User name \"%s\" is too long\n",
  821.             temp->pw_name);
  822.         ErrAbort("");
  823.     };
  824.     strcpy(userName, temp->pw_name);
  825. }
  826.  
  827. /*
  828.  * The following routine creates the public file name which
  829.  * holds the public file entry.
  830.  */
  831. char *
  832. MakePublicFileName(publicDirectoryName, publicKey)
  833.     char    *publicDirectoryName;
  834.     word32    publicKey[MAX_PUBLIC_KEY_SIZE];
  835. {    static    char    publicFileName[MAX_FILE_NAME_SIZE_IN_BYTES];
  836.     char    digits[50];
  837.     /*  public file entries are file names like:
  838.      * publicDirectory/p361ad90c
  839.      */
  840.     strcpy(publicFileName, publicDirectoryName);
  841.     (void) sprintf(digits, "/p%08lx_%08lx", publicKey[1], publicKey[2]);
  842.     strcat(publicFileName, digits);
  843.     return(publicFileName);
  844. };
  845.  
  846.  
  847. /*
  848.  * The following routine creates the names of the two
  849.  * "stable storage" files.
  850.  */
  851. void
  852. NameStableStorage(file1Name, file2Name)
  853.     char    file1Name[MAX_FILE_NAME_SIZE_IN_BYTES];
  854.     char    file2Name[MAX_FILE_NAME_SIZE_IN_BYTES];
  855. {    char    userName[MAX_USER_NAME_SIZE_IN_BYTES];
  856.  
  857.     strcpy(file1Name, STABLE1_DIRECTORY);
  858.     strcpy(file2Name, STABLE2_DIRECTORY);
  859.     strcat(file1Name, "/");
  860.     strcat(file2Name, "/");
  861.     GetUserName(userName);
  862.     if (5+strlen(file1Name)+strlen(userName)>=MAX_FILE_NAME_SIZE_IN_BYTES) {
  863.         fprintf(stderr, " File name \"%s%s\" too long\n",
  864.             file1Name, userName);
  865.         ErrAbort("");
  866.     };
  867.     if (5+strlen(file2Name)+strlen(userName)>=MAX_FILE_NAME_SIZE_IN_BYTES) {
  868.         fprintf(stderr, " File name \"%s%s\" too long\n",
  869.             file2Name, userName);
  870.         ErrAbort("");
  871.     };
  872.     strcat(file1Name, userName);
  873.     strcat(file2Name, userName);
  874.     strcat(file1Name, "1");
  875.     strcat(file2Name, "2");
  876. }
  877.  
  878. /*
  879.  * The following routine returns the file name after removing
  880.  * any preceding directory names.  Example input:
  881.  * "/usr/merkle/vorpal".  Example output: "vorpal"
  882.  */
  883. GetFileSuffix(fileName, suffixName)
  884.     char    *fileName;
  885.     char    suffixName[MAX_FILE_NAME_SIZE_IN_BYTES];
  886. {    int    i;
  887.  
  888.     i = strlen(fileName);
  889.     while( (fileName[i-1]!= '/') && (i > 0)) i--;
  890.     strcpy(suffixName, &fileName[i]);
  891. }
  892.  
  893.  
  894. /*
  895.  * The following routine creates and returns the name of the
  896.  * auxilliary information files.  Note that there are two
  897.  * auxilliary file names, only one of which is in use at any
  898.  * given time.  The one in use is selected by examining the
  899.  * binary variable "toggle".  The use of two auxilliary file
  900.  * names (used in a "ping-pong" fashion) eliminates timing problems
  901.  * that can arise when the signing process fails to go to
  902.  * a normal completion.
  903.  */
  904. char *
  905. AuxInfoFile(toggle)
  906.     int    toggle;
  907. {    char    userName[MAX_USER_NAME_SIZE_IN_BYTES];
  908.     static    char file1Name[MAX_FILE_NAME_SIZE_IN_BYTES];
  909.     static    char file2Name[MAX_FILE_NAME_SIZE_IN_BYTES];
  910.     static    int  flag = 0;
  911.  
  912.     if (flag == 0) {
  913.         flag = 1;
  914.         strcpy(file1Name, AUX_INFO_DIRECTORY);
  915.         strcpy(file2Name, AUX_INFO_DIRECTORY);
  916.         strcat(file1Name, "/");
  917.         strcat(file2Name, "/");
  918.         GetUserName(userName);
  919.         if (5+strlen(file1Name)+strlen(userName) >=
  920.             MAX_FILE_NAME_SIZE_IN_BYTES) {
  921.             fprintf(stderr, " File name \"%s%s\" too long\n",
  922.                 file1Name, userName);
  923.             ErrAbort("");
  924.         };
  925.         if (5+strlen(file2Name)+strlen(userName) >=
  926.             MAX_FILE_NAME_SIZE_IN_BYTES) {
  927.             fprintf(stderr, " File name \"%s%s\" too long\n",
  928.                 file2Name, userName);
  929.             ErrAbort("");
  930.         };
  931.         strcat(file1Name, userName);
  932.         strcat(file2Name, userName);
  933.         strcat(file1Name, "Aux0");
  934.         strcat(file2Name, "Aux1");
  935.         };
  936.     if (toggle==0)
  937.         return(file1Name);
  938.     else
  939.         return(file2Name);
  940. }
  941.  
  942. /*
  943.  * A simple error testing routine.  If the variable is not between
  944.  * "low" and "high" inclusive, then print out the error message and
  945.  * abort.
  946.  */
  947. void 
  948. RangeCheck (value, low, high, message)
  949.     int     value;
  950.     int     low;
  951.     int     high;
  952.     char   *message;
  953. {
  954.     if ((value < low) || (value > high)) {
  955.         fprintf(stderr, "Error: %s is %d which is outside [%d .. %d]\n",
  956.             message, value, low, high);
  957.         ErrAbort ("");
  958.     };
  959. }
  960.  
  961. /* PORTABILITY WARNING:  This routine assumes that file names
  962.  * use "/" to separate the directory names in a full path name.
  963.  * The following routine creates the signature file name
  964.  * given the file name.  Basically, if fileName is
  965.  * /this/that/other/name
  966.  * then the signature file is
  967.  * /this/that/other/.JZname
  968.  */
  969. void
  970. makeSigFileName(fileName, sigFileName)
  971.     char    *fileName;
  972.     char    sigFileName[MAX_FILE_NAME_SIZE_IN_BYTES];
  973. {    int    length;
  974.     int    slashLoc;
  975.     char    tempName[MAX_FILE_NAME_SIZE_IN_BYTES];
  976.  
  977.     length = strlen(fileName);
  978.     if (length > MAX_FILE_NAME_SIZE_IN_BYTES-6) {
  979.         fprintf(stderr, "Signature file name \"%s\" too long.\n",
  980.             fileName);
  981.         ErrAbort("");
  982.     };
  983.     for(slashLoc = length-1; slashLoc >= 0; slashLoc--)
  984.         if(fileName[slashLoc] == '/') break;
  985.     strcpy(tempName, &fileName[slashLoc+1]);
  986.     strcpy(sigFileName, fileName);
  987.     sigFileName[slashLoc+1] = 0; /* terminate after the '/' */
  988.     strcat(sigFileName, ".");
  989.     strcat(sigFileName, SHORT_UNUSUAL_STRING);
  990.     strcat(sigFileName, tempName);
  991. }
  992.  
  993. /**
  994.    The following rather awful computation determines how many
  995.    "counts" there should be.  Basically, its
  996.  
  997.    securitySizeInBits / noOfBitsPerVerifier + fudgeFactor
  998.  
  999.    where your really have to add and subtract 1's to make things
  1000.    work out exactly right.  The fudgeFactor provides enough
  1001.    additional counts to take care of the "check" field.
  1002.  
  1003.    Examples:
  1004.     for a 64-bit  word and 4 bits per verifier, we need 18 counts
  1005.     for a 96-bit  word and 4 bits per verifier, we need 27 counts
  1006.     for a 128-bit word and 4 bits per verifier, we need 35 counts
  1007.     for a 64-bit  word and 8 bits per verifier, we need 10 counts
  1008.  
  1009. */
  1010.  
  1011. int 
  1012. ComputeNumberOfCounts (securitySize, wordSizeInBits, noOfBitsPerVerifier)
  1013.     int     securitySize;
  1014.     int     wordSizeInBits;
  1015.     int     noOfBitsPerVerifier;
  1016. {    int     noOfCounts;
  1017.     word32 maxSumOfCounts;
  1018.  
  1019.     noOfCounts = (wordSizeInBits * securitySize - 1) /
  1020.         noOfBitsPerVerifier + 1;
  1021.     /*
  1022.      * 1L << noOfBitsPerVerifier - 1 is really 2**noOfBitsPerVerifier-1
  1023.      */
  1024.     maxSumOfCounts = noOfCounts * ((1L << noOfBitsPerVerifier) - 1);
  1025.     noOfCounts += (SizeInBits (maxSumOfCounts) - 1) /
  1026.         noOfBitsPerVerifier + 1;
  1027.     return (noOfCounts);
  1028. }
  1029.  
  1030. /*
  1031.  * The following routine unpacks the 32-bits in "header" and
  1032.  * puts them into the specified output variables.
  1033.  * Yes, it would be nice to use bit fields, but there's
  1034.  * no guarantee that the bit fields would be laid out in
  1035.  * the same fashion from compiler to compiler.
  1036.  */
  1037. void
  1038. UnPackHeader (    header, hashMethodPtr,
  1039.         securitySizePtr, parameterSizePtr,
  1040.         noOfBitsPerVerifierPtr, hashValueSizePtr, noOfCountsPtr)
  1041.     word32 header;
  1042.     int *hashMethodPtr;
  1043.     int *securitySizePtr;
  1044.     int *parameterSizePtr;
  1045.     int *noOfBitsPerVerifierPtr;
  1046.     int *hashValueSizePtr;
  1047.     int *noOfCountsPtr;
  1048. {    *hashMethodPtr = header >> 16;
  1049.     *securitySizePtr = header>>8 & 0xf;
  1050.     *parameterSizePtr = header>>4 & 0xf;
  1051.     *noOfBitsPerVerifierPtr = header & 0xf;
  1052.     *hashValueSizePtr = 2 * (*securitySizePtr);
  1053.     *noOfCountsPtr = ComputeNumberOfCounts (*securitySizePtr,
  1054.                WORD_SIZE_IN_BITS, *noOfBitsPerVerifierPtr);
  1055.     /*  range check everything */
  1056.     switch (*hashMethodPtr) {
  1057.         case SNEFRU4_METHOD:    break;
  1058.         case MD4_METHOD:    break;
  1059.         default:
  1060.             ErrAbort("bad hash method");
  1061.         };
  1062.     RangeCheck (*securitySizePtr, 2, MAX_SECURITY_SIZE,
  1063.             "security size");
  1064.     RangeCheck (*parameterSizePtr, 2, MAX_PARAMETER_SIZE,
  1065.             "parameter size");
  1066.     RangeCheck (*noOfBitsPerVerifierPtr, 0, MAX_BITS_PER_VERIFIER,
  1067.             "bits per verifier");
  1068.     RangeCheck (*noOfCountsPtr, 0, MAX_NO_OF_COUNTS,
  1069.             "number of counts");
  1070. }
  1071.  
  1072. /*
  1073.  * The following routine packs the given input variables
  1074.  * into *headerPtr.
  1075.  */
  1076. void
  1077. PackHeader (    headerPtr, hashMethod,
  1078.         securitySize, parameterSize, noOfBitsPerVerifier)
  1079.     word32 *headerPtr;
  1080.     int hashMethod;
  1081.     int securitySize;
  1082.     int parameterSize;
  1083.     int noOfBitsPerVerifier;
  1084. {    switch (hashMethod) {
  1085.         case SNEFRU4_METHOD:    break;
  1086.         case MD4_METHOD:    break;
  1087.         default:
  1088.             ErrAbort("bad hash method");
  1089.         };
  1090.     RangeCheck (securitySize, 2, MAX_SECURITY_SIZE,
  1091.             "security size");
  1092.     RangeCheck (parameterSize, 2, MAX_PARAMETER_SIZE,
  1093.             "parameter size");
  1094.     RangeCheck (noOfBitsPerVerifier, 0, MAX_BITS_PER_VERIFIER,
  1095.             "number of bits per verifier");
  1096.  
  1097.     *headerPtr =    hashMethod << 16    |
  1098.             securitySize << 8    |
  1099.             parameterSize << 4    |
  1100.             noOfBitsPerVerifier;
  1101. }
  1102.  
  1103. /*
  1104.  * The following routine computes the size of the public key
  1105.  * by examining the first word (32 bits) of the public key.
  1106.  * The first word encodes the hash method, the security size,
  1107.  * the parameter size, and other good stuff.  The size of
  1108.  * the public key in 32-bit words is just the security size
  1109.  * plus the parameter size plus 1 (the size of the 32-bit header).
  1110.  */
  1111. int
  1112. ComputePublicKeySize(publicKey)
  1113. word32 publicKey[MAX_PUBLIC_KEY_SIZE];
  1114. {    int hashMethod;
  1115.     int securitySize;
  1116.     int parameterSize;
  1117.     int noOfBitsPerVerifier;
  1118.     int hashValueSize;
  1119.     int noOfCounts;
  1120.  
  1121.     if (publicKey[0] == 0) return(1);
  1122.     UnPackHeader (    publicKey[0], &hashMethod,
  1123.             &securitySize, ¶meterSize,
  1124.             &noOfBitsPerVerifier, &hashValueSize, &noOfCounts);
  1125.     return(securitySize + parameterSize + 1);
  1126. }
  1127.  
  1128. /*
  1129.  * The following routine converts an array of word32 to a byte
  1130.  * array. It is primarily intended to eliminate the byte-ordering problem.
  1131.  * VAXes order the bytes in a character array differently than SUN's do. This
  1132.  * routine is not needed on SUNs (or other big-endian machines).
  1133.  */
  1134. void 
  1135. ConvertLongToChar (wordBuffer, charBuffer, wordLength)
  1136.     word32    wordBuffer[ /* wordLength */ ];/* input buffer */
  1137.     char    charBuffer[ /* wordLength * 4 */ ]; /* output buffer */
  1138.     int    wordLength;
  1139. {    int     i;
  1140.     word32 temp;
  1141.  
  1142.     for (i = 0; i < wordLength; i++) {
  1143.         temp = wordBuffer[i];
  1144.         charBuffer[4 * i + 0] = (temp >> 24) & 0xff;
  1145.         charBuffer[4 * i + 1] = (temp >> 16) & 0xff;
  1146.         charBuffer[4 * i + 2] = (temp >>  8) & 0xff;
  1147.         charBuffer[4 * i + 3] = (temp >>  0) & 0xff;
  1148.     };
  1149. };
  1150.  
  1151. /*
  1152.  * The following routine converts a byte array to an array of word32.
  1153.  * It is intended to eliminate the byte-ordering problem. VAXes order
  1154.  * the bytes in a character array differently than SUN's do.  Some
  1155.  * machines do REALLY horrible things -- this routine should be
  1156.  * fairly portable (if not blindingly fast).
  1157.  */
  1158. void 
  1159. ConvertBytes (buffer, wordBuffer, charCount)
  1160.     char    buffer[];    /*  input buffer */
  1161.     word32    wordBuffer[];    /*  output buffer */
  1162.     int    charCount;
  1163. {    int     i;
  1164.     int     wordCount;
  1165.     word32 t0, t1, t2, t3;
  1166.  
  1167.     if (charCount <= 0) return;
  1168.     wordCount = (charCount+3)>>2;
  1169.     for (i = 0; i < wordCount; i++) {
  1170.         t0 = buffer[4 * i + 0];
  1171.         t1 = buffer[4 * i + 1];
  1172.         t2 = buffer[4 * i + 2];
  1173.         t3 = buffer[4 * i + 3];
  1174.         t0 &= 0xff;
  1175.         t1 &= 0xff;
  1176.         t2 &= 0xff;
  1177.         t3 &= 0xff;
  1178.         wordBuffer[i] = (t0 << 24) | (t1 << 16) | (t2 << 8) | t3;
  1179.     };
  1180.     /* Get rid of the bottom bytes that aren't wanted */
  1181.     switch (charCount&3) {
  1182.         case 0:
  1183.             break;
  1184.         case 1:    wordBuffer[wordCount-1] &= 0xff000000L;
  1185.             break;
  1186.         case 2:    wordBuffer[wordCount-1] &= 0xffff0000L;
  1187.             break;
  1188.         case 3:    wordBuffer[wordCount-1] &= 0xffffff00L;
  1189.     };
  1190. }
  1191.  
  1192.  
  1193. /*
  1194.  * The following routine increments a "path" location. This is a 32-bit word
  1195.  * that encodes a "path" up a binary tree.  Succeeding bits in the word
  1196.  * following the first "1" bit show whether to take the left or right branch
  1197.  * in the "path" from the root of the tree to any particular leaf.
  1198.  * 
  1199.  * When a "path" is incremented, it might overflow. In this case, the path value
  1200.  * is left unchanged and the routine returns the value "PATHOVERFLOW".
  1201.  * Otherwise the routine returns the value "NOPATHOVERFLOW"
  1202.  */
  1203. int 
  1204. BumpPath (pathPtr)
  1205.     word32 *pathPtr;
  1206. {    /*
  1207.      * If the bit pattern passed in looks like: 000...00111....11
  1208.      * 
  1209.      * then, by definition, incrementing this by one causes an "overflow" in
  1210.      * the path description because it alters the location of the leading
  1211.      * "1" bit.
  1212.      */
  1213.     if (SizeInBits (*pathPtr) != SizeInBits ((*pathPtr) + 1))
  1214.         return (PATHOVERFLOW);
  1215.     else {
  1216.         (*pathPtr)++;
  1217.         return (NOPATHOVERFLOW);
  1218.     };
  1219. }
  1220.  
  1221. /*
  1222.  * The following routine sets a single bit in "array" at the designated
  1223.  * offset
  1224.  */
  1225. void 
  1226. SetBit (array, bitOffset)
  1227.     word32 array[];
  1228.     int     bitOffset;
  1229. {    int     wordOffset;
  1230.     word32 mask;
  1231.  
  1232.     /*
  1233.      * compute word and bit offsets for a 32-bit word size. Yes,
  1234.      * "WORD_SIZE_IN_BITS" is 32.  If not, watch out!
  1235.      */
  1236.     wordOffset = bitOffset / WORD_SIZE_IN_BITS;
  1237.     bitOffset %= WORD_SIZE_IN_BITS;
  1238.     mask = 1;
  1239.     mask <<= 31;        /* Set the topmost bit */
  1240.     /* set the bit... */
  1241.     array[wordOffset] |= (mask >> bitOffset);
  1242. }
  1243.  
  1244. /*
  1245.  * The following routine grabs noOfBits bits from the given array, at the
  1246.  * given bitOffset.  Bits beyond the array limit are defined to be 0
  1247.  */
  1248. word32 
  1249. FetchBits (array, arrayLimit, bitOffset, noOfBits)
  1250.     word32 array[ /* arrayLimit */ ];
  1251. int     arrayLimit;
  1252. int     bitOffset;
  1253. int     noOfBits;
  1254. {    word32 temp1, temp2;
  1255.     int     wordOffset;
  1256.  
  1257.     /*
  1258.      * compute word and bit offsets for a 32-bit word size. Yes,
  1259.      * "WORD_SIZE_IN_BITS" is 32.  If not, watch out!
  1260.      */
  1261.     wordOffset = bitOffset / WORD_SIZE_IN_BITS;
  1262.     bitOffset %= WORD_SIZE_IN_BITS;
  1263.  
  1264.  
  1265.     /* fetch the (possibly two) words involved from the array */
  1266.     temp1 = array[wordOffset];
  1267.     temp2 = array[wordOffset + 1];
  1268.  
  1269.     /* check for references beyond array limit */
  1270.     if (wordOffset >= arrayLimit)
  1271.         temp1 = 0;
  1272.     if (wordOffset + 1 >= arrayLimit)
  1273.         temp2 = 0;
  1274.  
  1275.  
  1276.     /* grab the bits from the right spot */
  1277.     temp1 <<= bitOffset;
  1278.     temp1 >>= WORD_SIZE_IN_BITS - noOfBits;
  1279.  
  1280.     /* "or" in the bits from the second word, if needed */
  1281.     if (bitOffset + noOfBits > WORD_SIZE_IN_BITS)
  1282.         temp1 |= (temp2 >> (2 * WORD_SIZE_IN_BITS
  1283.                 - bitOffset - noOfBits));
  1284.     /* and return the bits! */
  1285.     return (temp1);
  1286. }
  1287.  
  1288. void 
  1289. DownLeft (p, n)
  1290.     word32 p[ /* n */ ];
  1291.     int     n;
  1292. {    word32 overFlow;
  1293.     int     temp;
  1294.     int     i;
  1295.  
  1296.     /* grab the bottom bit from the last word of the parameter */
  1297.     overFlow = p[n - 1] & 1;
  1298.     for (i = 0; i < n; i++) {
  1299.         temp = p[i] & 1;
  1300.         p[i] >>= 1;
  1301.         p[i] |= overFlow << 31;
  1302.         overFlow = temp;
  1303.     };
  1304. };
  1305.  
  1306. void 
  1307. DownRight (p, n)
  1308.     word32 p[ /* n */ ];
  1309. {    word32 overFlow;
  1310.     int     temp;
  1311.     int     i;
  1312.  
  1313.     /* grab the bottom bit from the last word of the parameter */
  1314.     overFlow = p[n - 1] & 1;
  1315.     overFlow ^= 1;        /* flip the bit */
  1316.     for (i = 0; i < n; i++) {
  1317.         temp = p[i] & 1;
  1318.         p[i] >>= 1;
  1319.         p[i] |= overFlow << 31;
  1320.         overFlow = temp;
  1321.     };
  1322. };
  1323.  
  1324. void 
  1325. UpRight (p, n)
  1326.     word32 p[ /* n */ ];
  1327.     int     n;
  1328. {    word32 overFlow;
  1329.     int     temp;
  1330.     int     i;
  1331.  
  1332.     /* Quick test for overflow  */
  1333.     if ((p[0] >> (WORD_SIZE_IN_BITS - 4)) == 0)
  1334.         ErrAbort (" Parameter overflow!");
  1335.  
  1336.     /* grab the top bit from the first word of the parameter */
  1337.     overFlow = (p[0] >> 31) & 1;
  1338.     for (i = n - 1; i >= 0; i--) {
  1339.         temp = (p[i] >> 31) & 1;
  1340.         p[i] <<= 1;
  1341.         p[i] |= overFlow;
  1342.         overFlow = temp;
  1343.     };
  1344. };
  1345.  
  1346. void 
  1347. UpLeft (p, n)
  1348.     word32 p[ /* n */ ];
  1349. int     n;            /* length (in 32-bit words) of the parameter */
  1350. {    word32 overFlow;
  1351.     int     temp;
  1352.     int     i;
  1353.  
  1354.     /* Quick test for overflow  */
  1355.     if ((p[0] >> (WORD_SIZE_IN_BITS - 4)) == 0)
  1356.         ErrAbort (" Parameter overflow!");
  1357.  
  1358.     /* grab the top bit from the first word of the parameter */
  1359.     overFlow = (p[0] >> 31) & 1;
  1360.     for (i = n - 1; i >= 0; i--) {
  1361.         temp = (p[i] >> 31) & 1;
  1362.         p[i] <<= 1;
  1363.         p[i] |= overFlow;
  1364.         overFlow = temp;
  1365.     };
  1366.     p[n - 1] ^= 1;        /* flip the bottom bit  */
  1367. };
  1368.  
  1369.  
  1370. void 
  1371. UpPath (p, parameterSize, path)
  1372.     word32 p[];
  1373.     word32 path;
  1374. {    word32 reversePath;
  1375.     int     pathLength;
  1376.  
  1377.     if (path <= 0)
  1378.         ErrAbort ("logic error -- path is not positive");
  1379.     reversePath = 0;
  1380.     /* First, reverse the bits  */
  1381.     for (pathLength = -1; path != 0; pathLength++) {
  1382.         reversePath <<= 1;
  1383.         reversePath |= (path & 1);
  1384.         path >>= 1;
  1385.     };
  1386.     /*
  1387.      * and throw away the bottom bit (which used to be the top bit)
  1388.      * because it's always 1
  1389.      */
  1390.     reversePath >>= 1;
  1391.  
  1392.     /* and go up the path!  */
  1393.  
  1394.     while (pathLength != 0) {
  1395.         if ((reversePath & 1) == 1)
  1396.             UpLeft (p, parameterSize);
  1397.         else
  1398.             UpRight (p, parameterSize);
  1399.         reversePath >>= 1;
  1400.         pathLength--;
  1401.     };
  1402. }
  1403.  
  1404. void 
  1405. HashThreeItems (out, outSize,
  1406.         in1, in1Size,
  1407.         in2, in2Size,
  1408.         in3, in3Size,
  1409.         hashMethod)
  1410.     word32 out[];
  1411.     int     outSize;
  1412.     word32 in1[];
  1413.     int     in1Size;
  1414.     word32 in2[];
  1415.     int     in2Size;
  1416.     word32 in3[];
  1417.     int     in3Size;
  1418.     int     hashMethod;
  1419. {    word32 tempIn[MAX_INPUT_BLOCK_SIZE];
  1420.  
  1421.     if ((in1Size + in2Size + in3Size) > MAX_INPUT_BLOCK_SIZE)
  1422.         ErrAbort ("Input to HashThreeItems is too large");
  1423.     Copy (&tempIn[0], in1, in1Size);
  1424.     Copy (&tempIn[in1Size], in2, in2Size);
  1425.     Copy (&tempIn[in1Size + in2Size], in3, in3Size);
  1426.     HashAny (out, outSize, tempIn, in1Size + in2Size + in3Size, hashMethod);
  1427. };
  1428.  
  1429. void 
  1430. HashTwoItems (out, outSize,
  1431.           in1, in1Size,
  1432.           in2, in2Size,
  1433.           hashMethod)
  1434.     word32 out[];
  1435.     int     outSize;
  1436.     word32 in1[];
  1437.     int     in1Size;
  1438.     word32 in2[];
  1439.     int     in2Size;
  1440.     int     hashMethod;
  1441. {    word32 empty[1];
  1442.     HashThreeItems (out, outSize, in1, in1Size,
  1443.         in2, in2Size, empty, 0, hashMethod);
  1444. };
  1445.  
  1446. /*
  1447.  * This routine increments a 64-bit counter by the given increment.
  1448.  */
  1449. void
  1450. Increment64BitCounter (counter, increment)
  1451.     word32 counter[2];
  1452.     long int increment;
  1453. {    word32 maxInt = 0xffffffffL;
  1454.  
  1455.     if ( (maxInt-counter[1]) < increment) {
  1456.         /*  Overflow from the lower 32 bits  */
  1457.         if (counter[0] == maxInt)
  1458.             ErrAbort("64-bit counter overflowed");
  1459.         /* bump the upper 32 bits  */
  1460.         counter[0]++;
  1461.         /* and then increment the lower 32 bits */
  1462.         /* without ever overflowing! */
  1463.         counter[1] = maxInt-counter[1];
  1464.         counter[1] = increment - counter[1];
  1465.     }
  1466.     else
  1467.     /* increment the total number of bits read */
  1468.     counter[1] += increment;
  1469. }
  1470.  
  1471. /*  Read a "chunk" of "chunkSize" 32-bit words from the given
  1472.  *  file.  Take care of any byte ordering problems involved
  1473.  *  in reading the 32-bit input values
  1474.  */
  1475. int
  1476. ReadChunk (file, chunk, chunkSize)
  1477.     FILE    *file;
  1478.     word32    *chunk;
  1479.     int    chunkSize;
  1480. {    char    temp[4*SNEFRU_INPUT_BLOCK_SIZE];
  1481.     int    byteCount;
  1482.     int    i;
  1483.  
  1484.     byteCount = fread(temp, 1, 4*chunkSize, file);
  1485.     if (ferror(file) != 0) {
  1486.         ErrAbort("Can't read from input file");
  1487.     };
  1488.     for (i=byteCount; i<4*chunkSize; i++)
  1489.         temp[i] = 0;
  1490.     ConvertBytes(temp, chunk, 4*chunkSize);
  1491.     return(byteCount);
  1492. }
  1493.  
  1494. void
  1495. HashFile (inputFile, hashValue, hashValueSize, hashMethod)
  1496.     FILE    *inputFile;
  1497.     word32    hashValue[MAX_HASH_VALUE_SIZE];
  1498.     int    hashValueSize;
  1499. {    switch (hashMethod) {
  1500.     case MD4_METHOD: 
  1501.         Md4HashFile(inputFile, hashValue, hashValueSize);
  1502.         break;
  1503.     case SNEFRU4_METHOD:
  1504.         SnefruHashFile(inputFile, hashValue, hashValueSize, hashMethod);
  1505.         break;
  1506.     };
  1507. }
  1508.  
  1509. /*  Write out information to one of the "stable storage files".
  1510.  *  The stable storage file is small, so it's kept in readable
  1511.  *  ASCII format.  This simplifies debugging, but makes the
  1512.  *  following routine more complex than a simple series of binary
  1513.  *  writes.
  1514.  */
  1515. void 
  1516. WriteOneStableStorageFile (stableStorageFile,
  1517.                 machineKey,
  1518.                 publicKey,
  1519.                 hashedUserKey,
  1520.                 path,
  1521.                 top,
  1522.                 toggle,
  1523.                 OTTsize)
  1524.     FILE    *stableStorageFile;
  1525.     word32    machineKey[MACHINE_KEY_SIZE];
  1526.     word32    publicKey[MAX_PUBLIC_KEY_SIZE];
  1527.     word32    hashedUserKey[HASHED_USER_KEY_SIZE];
  1528.     word32    path[MAX_STACK_DEPTH];
  1529.     int     top;
  1530.     int    toggle;
  1531. {    int     i;
  1532.     int     printCode;
  1533.     int    publicKeySize;
  1534.  
  1535.     RangeCheck(top, 0, MAX_STACK_DEPTH-1, "top");
  1536.     rewind(stableStorageFile);
  1537.     printCode = fprintf (stableStorageFile, "machineKey =");
  1538.     if (printCode <= 0)
  1539.         ErrAbort ("can't write string to stable storage");
  1540.     for (i = 0; i < MACHINE_KEY_SIZE; i++) {
  1541.         printCode = fprintf (stableStorageFile,
  1542.                 " %08lx", machineKey[i]);
  1543.         if (printCode <= 0)
  1544.             ErrAbort ("bad write to stable storage");
  1545.         if ((i % 4 == 3) && (MACHINE_KEY_SIZE - 1 > i))
  1546.             printCode = fprintf (stableStorageFile,
  1547.                     "\n            ");
  1548.         if (printCode <= 0)
  1549.             ErrAbort ("bad string write to stable storage");
  1550.     };
  1551.     printCode = fprintf (stableStorageFile, "\nhashedUserKey =");
  1552.     if (printCode <= 0)
  1553.         ErrAbort ("can't write string to stable storage");
  1554.     for (i = 0; i < HASHED_USER_KEY_SIZE; i++) {
  1555.         printCode = fprintf (stableStorageFile,
  1556.                 " %08lx", hashedUserKey[i]);
  1557.         if (printCode <= 0)
  1558.             ErrAbort ("bad write to stable storage");
  1559.         if ((i % 4 == 3) && (HASHED_USER_KEY_SIZE - 1 > i))
  1560.             printCode = fprintf (stableStorageFile,
  1561.                     "\n            ");
  1562.         if (printCode <= 0)
  1563.             ErrAbort ("bad string write to stable storage");
  1564.     };
  1565.     printCode = fprintf (stableStorageFile, "\npublicKey  =");
  1566.     if (printCode <= 0)
  1567.         ErrAbort ("can't write string to stable storage");
  1568.     publicKeySize = ComputePublicKeySize(publicKey);
  1569.     for (i = 0; i < publicKeySize; i++) {
  1570.         printCode = fprintf (stableStorageFile,
  1571.                 " %08lx", publicKey[i]);
  1572.         if (printCode <= 0)
  1573.             ErrAbort ("bad public key write to stable storage");
  1574.     };
  1575.     printCode = fprintf (stableStorageFile, "\ntoggle = %d\n", toggle);
  1576.     if (printCode <= 0)
  1577.         ErrAbort ("can't write toggle to stable storage");
  1578.     printCode = fprintf (stableStorageFile, "OTTsize = %d\n", OTTsize);
  1579.     if (printCode <= 0)
  1580.         ErrAbort ("can't write OTTsize to stable storage");
  1581.     printCode = fprintf (stableStorageFile, "top = %d\npath =", top);
  1582.     if (printCode <= 0)
  1583.         ErrAbort ("can't write top to stable storage");
  1584.     for (i = 0; i <= top; i++) {
  1585.         printCode = fprintf (stableStorageFile, " %lx", path[i]);
  1586.         if (printCode <= 0)
  1587.             ErrAbort ("bad path write to stable storage");
  1588.     };
  1589.     printCode = fprintf (stableStorageFile, "\n");
  1590.     if (printCode <= 0)
  1591.         ErrAbort ("can't write string to stable storage");
  1592. }
  1593.  
  1594. /*
  1595.  * The following routines write the machine key, the current signature
  1596.  * path, and the public key redundantly to two "stable storage" files.
  1597.  * Stable storage can be relied upon not to be changed, altered, or lost in
  1598.  * some unpleasant fashion.  As long as one of the two "stable storage" files
  1599.  * is intact, the aux info can be recovered.  If the two stable storage
  1600.  * files are kept on separate disk drives, then it is unlikely that both will
  1601.  * be lost simultaneously.
  1602.  * 
  1603.  * Stable storage should not be backed up.  If one stable storage file is
  1604.  * damaged, it should be re-initialized from the other stable storage file.
  1605.  * In the unlikely event that both stable storage files are damaged, then no
  1606.  * further messages should be signed with this signing key.  A new
  1607.  * signing-key/checking-key pair should be issued.
  1608.  * 
  1609.  * Note that loss of the secret signing key is a nuisance, but does not cause
  1610.  * any significant damage.  Messages already signed continue to be valid even
  1611.  * if the secret signing key is destroyed.  The newly issued secret signing
  1612.  * key can be used to sign new messages.  If interruption of service is an
  1613.  * issue, then a second signing-key/checking-key pair can be prepared for the
  1614.  * user in advance of need.  This will also provide uninterrupted service to
  1615.  * the user in case of other problems, such as theft, destruction, loss,
  1616.  * compromise, etc.
  1617.  * 
  1618.  * (Note that these precautions will prevent compromise of the machine
  1619.  * key and will also prevent re-signing of two different messages with
  1620.  * the same one-time signature.  The latter would seriously
  1621.  * jeopordize security).
  1622.  * 
  1623.  * Exactly how this "stable storage" is realized in any particular instance is
  1624.  * left up to the implementor.
  1625.  */
  1626. void 
  1627. WriteStableStorage (file1, file2, machineKey,
  1628.             publicKey, hashedUserKey,
  1629.             path, top, toggle, OTTsize)
  1630.     FILE    *file1;
  1631.     FILE    *file2;
  1632.     word32    machineKey[];
  1633.     word32    publicKey[MAX_PUBLIC_KEY_SIZE];
  1634.     word32    hashedUserKey[HASHED_USER_KEY_SIZE];
  1635.     word32    path[];
  1636.     int     top;
  1637.     int    toggle;
  1638.     int    OTTsize;
  1639. {    WriteOneStableStorageFile (file1, machineKey, publicKey,
  1640.                     hashedUserKey, path,
  1641.                     top, toggle, OTTsize);
  1642.     WriteOneStableStorageFile (file2, machineKey, publicKey,
  1643.                     hashedUserKey, path,
  1644.                     top, toggle, OTTsize);
  1645. };
  1646.  
  1647.  
  1648. /*
  1649.  * The following two routines read the machine key and the path from stable
  1650.  * storage.  If the two files have conflicting values, abort at once.
  1651.  */
  1652. void 
  1653. ReadOneStableStorageFile (stableStorageFile, machineKey, publicKey,
  1654.                 hashedUserKey, path,
  1655.                 topPtr, togglePtr, OTTsizePtr)
  1656.     FILE    *stableStorageFile;
  1657.     word32    machineKey[MACHINE_KEY_SIZE];
  1658.     word32    publicKey[MAX_PUBLIC_KEY_SIZE];
  1659.     word32    hashedUserKey[HASHED_USER_KEY_SIZE];
  1660.     word32    path[MAX_STACK_DEPTH];
  1661.     int    *topPtr;
  1662.     int    *togglePtr;
  1663.     int    *OTTsizePtr;
  1664. {    int     i;
  1665.     int     scanCode;
  1666.     int    publicKeySize;
  1667.  
  1668.     scanCode = fscanf (stableStorageFile, " machineKey = ");
  1669.     if (scanCode != 0)
  1670.         ErrAbort ("can't read string from stable storage");
  1671.     for (i = 0; i < MACHINE_KEY_SIZE; i++) {
  1672.         scanCode = fscanf (stableStorageFile, " %lx", &machineKey[i]);
  1673.         if (scanCode != 1)
  1674.             ErrAbort ("bad read from stable storage");
  1675.     };
  1676.     scanCode = fscanf (stableStorageFile, " hashedUserKey = ");
  1677.     if (scanCode != 0)
  1678.         ErrAbort ("can't read string from stable storage");
  1679.     for (i = 0; i < HASHED_USER_KEY_SIZE; i++) {
  1680.         scanCode = fscanf (stableStorageFile,
  1681.             " %lx", &hashedUserKey[i]);
  1682.         if (scanCode != 1)
  1683.             ErrAbort ("bad read from stable storage");
  1684.     };
  1685.  
  1686.     /*  Read in the public key */
  1687.     scanCode = fscanf (stableStorageFile, " publicKey = ");
  1688.     if (scanCode != 0)
  1689.         ErrAbort ("can't read string from stable storage");
  1690.     scanCode = fscanf (stableStorageFile, " %lx", publicKey);
  1691.     if (scanCode != 1)
  1692.         ErrAbort ("bad path read from stable storage");
  1693.     publicKeySize = ComputePublicKeySize(publicKey);
  1694.     for (i = 1; i < publicKeySize; i++) {
  1695.         scanCode = fscanf (stableStorageFile, " %lx", &publicKey[i]);
  1696.         if (scanCode != 1)
  1697.             ErrAbort ("bad path read from stable storage");
  1698.     };
  1699.  
  1700.     scanCode = fscanf (stableStorageFile,
  1701.         " toggle = %d", togglePtr);
  1702.     if (scanCode != 1)
  1703.         ErrAbort (
  1704.         "can't read toggle from stable storage");
  1705.     RangeCheck(*togglePtr, 0, 1, "toggle");
  1706.  
  1707.     scanCode = fscanf (stableStorageFile,
  1708.         " OTTsize = %d", OTTsizePtr);
  1709.     if (scanCode != 1)
  1710.         ErrAbort (
  1711.         "can't read OTTsize from stable storage");
  1712.     RangeCheck(*OTTsizePtr, 4, MAX_OTT_SIZE, "OTT size");
  1713.  
  1714.     scanCode = fscanf (stableStorageFile, " top = %d path =", topPtr);
  1715.     if (scanCode != 1)
  1716.         ErrAbort ("can't read top from stable storage");
  1717.  
  1718.     if ((*topPtr) < 0)
  1719.         ErrAbort ("top negative");
  1720.     if ((*topPtr) >= MAX_STACK_DEPTH)
  1721.         ErrAbort ("top too big");
  1722.  
  1723.     for (i = 0; i <= *topPtr; i++) {
  1724.         scanCode = fscanf (stableStorageFile, " %lx", &path[i]);
  1725.         if (scanCode != 1)
  1726.             ErrAbort ("bad path read from stable storage");
  1727.     };
  1728. }
  1729.  
  1730.  
  1731. /*
  1732.  * Read the inputs from both files, and then compare them. If they disagree,
  1733.  * abort.
  1734.  */
  1735. void 
  1736. ReadStableStorage (file1, file2, machineKey, publicKey,
  1737.             hashedUserKey, path, topPtr, togglePtr, OTTsizePtr)
  1738.     FILE    *file1;
  1739.     FILE    *file2;
  1740.     word32    machineKey[MACHINE_KEY_SIZE];
  1741.     word32    publicKey[MAX_PUBLIC_KEY_SIZE];
  1742.     word32    hashedUserKey[HASHED_USER_KEY_SIZE];
  1743.     word32    path[MAX_STACK_DEPTH];
  1744.     int    *topPtr;
  1745.     int    *togglePtr;
  1746.     int    *OTTsizePtr;
  1747. {    word32    tempMachineKey[MACHINE_KEY_SIZE];
  1748.     word32    tempPublicKey[MAX_PUBLIC_KEY_SIZE];
  1749.     word32    tempPath[MAX_STACK_DEPTH];
  1750.     int    publicKeySize;
  1751.     int    tempTop;
  1752.     int    tempToggle;
  1753.     int    tempOTTsize;
  1754.     int    i;
  1755.  
  1756.     ReadOneStableStorageFile (file1, machineKey, publicKey,
  1757.         hashedUserKey, path, topPtr, togglePtr, OTTsizePtr);
  1758.  
  1759.     ReadOneStableStorageFile (file2, tempMachineKey, tempPublicKey,
  1760.         hashedUserKey, tempPath, &tempTop, &tempToggle, &tempOTTsize);
  1761.  
  1762.     if (tempTop != (*topPtr))
  1763.         ErrAbort ("conflicting stable storage for \"top\"");
  1764.  
  1765.     if (tempToggle != (*togglePtr))
  1766.     ErrAbort ("conflicting stable storage for \"toggle\"");
  1767.  
  1768.     if (tempOTTsize!= (*OTTsizePtr))
  1769.     ErrAbort ("conflicting stable storage for \"OTTsize\"");
  1770.  
  1771.     for (i = 0; i < tempTop; i++)
  1772.         if (tempPath[i] != path[i])
  1773.             ErrAbort ("conflicting stable storage for path");
  1774.  
  1775.     for (i = 0; i < MACHINE_KEY_SIZE; i++)
  1776.         if (machineKey[i] != tempMachineKey[i])
  1777.             ErrAbort ("conflicting stable storage for machine key");
  1778.  
  1779.     publicKeySize = ComputePublicKeySize(publicKey);
  1780.     for (i = 0; i < publicKeySize; i++)
  1781.         if (publicKey[i] != tempPublicKey[i])
  1782.             ErrAbort ("conflicting stable storage for public key");
  1783. }
  1784.  
  1785. /*
  1786.  * This routine reads in the data from the "signature file", which
  1787.  * is kept in binary, and then unpacks the data, performs range
  1788.  * checking, and generally converts the information in the file
  1789.  * into a useful internal format.
  1790.  */
  1791. void 
  1792. ReadSignature (sigFile,  hashMethodPtr,
  1793.         noOfSignaturesPtr, parameter, parameterSizePtr,
  1794.         securitySizePtr, hashValueSizePtr, noOfCountsPtr,
  1795.         noOfBitsPerVerifierPtr, signature, locationPtr,
  1796.         wordsToHashPtr, hashFromSig, dateTime32Ptr,
  1797.         binaryDataFieldSizePtr, message)
  1798.     FILE    *sigFile;
  1799.     int    *hashMethodPtr;
  1800.     int    *noOfSignaturesPtr;
  1801.     word32 parameter[MAX_PARAMETER_SIZE];
  1802.     int     *parameterSizePtr;
  1803.     int    *securitySizePtr;
  1804.     int    *hashValueSizePtr;
  1805.     int    *noOfCountsPtr;
  1806.     int    *noOfBitsPerVerifierPtr;
  1807.     word32 signature[MAX_SIGNATURE_SIZE];
  1808.     int    *locationPtr;
  1809.     word32    *wordsToHashPtr;
  1810.     word32    hashFromSig[MAX_HASH_VALUE_SIZE];
  1811.     word32    *dateTime32Ptr;
  1812.     int    *binaryDataFieldSizePtr;
  1813.     char    message[MAX_MESSAGE_SIZE_IN_BYTES];
  1814. {    int     lengthOfSignatureInBytes;
  1815.     word32    *locInSig;
  1816.     int    messageSize;
  1817.     char    charSignature[MAX_SIGNATURE_SIZE * 4];
  1818.  
  1819.     lengthOfSignatureInBytes =
  1820.         fread (charSignature, 1,
  1821.             MAX_SIGNATURE_SIZE * 4, sigFile);
  1822.     if (ferror(sigFile) != 0) {
  1823.         ErrAbort("Can't read from signature file");
  1824.     };
  1825.     ConvertBytes (charSignature, signature, MAX_SIGNATURE_SIZE * 4);
  1826.     /* dull error tests */
  1827.     RangeCheck (lengthOfSignatureInBytes, 0, MAX_SIGNATURE_SIZE * 4,
  1828.         "Signature length");
  1829.     if (lengthOfSignatureInBytes % 4 != 0)
  1830.         ErrAbort ("Signature length not a multiple of 4 bytes");
  1831.     /* We've read in the signature file */
  1832.  
  1833.     locInSig = signature;
  1834.     /*  now unpack the header */
  1835.     UnPackHeader( *locInSig, hashMethodPtr,
  1836.         securitySizePtr, parameterSizePtr,
  1837.         noOfBitsPerVerifierPtr, hashValueSizePtr, noOfCountsPtr);
  1838.     /*
  1839.      * return the number of one-time signatures used in this
  1840.      * signature
  1841.      */
  1842.     locInSig++;
  1843.     *noOfSignaturesPtr = (*locInSig) & 0xff;
  1844.     *wordsToHashPtr = (*locInSig)>>16;
  1845.     *binaryDataFieldSizePtr = ((*locInSig)>>8) & 0xff;
  1846.     locInSig++;
  1847.     *dateTime32Ptr = *locInSig;
  1848.     locInSig++;
  1849.     Copy(hashFromSig, locInSig, *hashValueSizePtr);
  1850.     locInSig += *hashValueSizePtr;
  1851.     Copy(parameter, locInSig, *parameterSizePtr);
  1852.     locInSig += *parameterSizePtr;
  1853.     messageSize = *wordsToHashPtr - *binaryDataFieldSizePtr-2;
  1854.     if (messageSize >= MAX_MESSAGE_SIZE-4)
  1855.         ErrAbort("Message size in signature is too big");
  1856.     ConvertLongToChar(locInSig, message, messageSize);
  1857.     locInSig += messageSize;
  1858.  
  1859.     /*
  1860.      * compute the start of the one-time signature count verifier block
  1861.      */
  1862.     *locationPtr = locInSig - signature;
  1863. };
  1864.  
  1865.  
  1866. /*
  1867.  * This routine checks an authentication path
  1868.  */
  1869. void 
  1870. CheckAuthenticationPath (checkValue, securitySize,
  1871.              parameter, parameterSize,
  1872.              hashMethod,
  1873.              path,
  1874.              branchVerifiers)
  1875.     word32 checkValue[];
  1876.     int     securitySize;
  1877.     word32 parameter[];
  1878.     int     parameterSize;
  1879.     int     hashMethod;
  1880.     word32 path;
  1881.     word32 branchVerifiers[];
  1882. {    while (path != 1) {
  1883.         if ((path & 1) == 1) {
  1884.  
  1885. #if DEBUG
  1886.             printf ("auth path bit is 1\n");
  1887.             PrintIt ("branchVerifiers=",
  1888.                  branchVerifiers, securitySize);
  1889.             PrintIt ("checkValue=", checkValue, securitySize);
  1890.             PrintIt ("parameter=", parameter, parameterSize);
  1891. #endif
  1892.             DownRight (parameter, parameterSize);
  1893.  
  1894.             HashThreeItems (checkValue, securitySize,
  1895.                     branchVerifiers, securitySize,
  1896.                     checkValue, securitySize,
  1897.                     parameter, parameterSize,
  1898.                     hashMethod);
  1899.         } else {
  1900.  
  1901. #if DEBUG
  1902.             printf ("auth path bit is 0\n");
  1903.             PrintIt ("checkValue=", checkValue, securitySize);
  1904.             PrintIt ("branchVerifiers=",
  1905.                  branchVerifiers, securitySize);
  1906.             PrintIt ("parameter=", parameter, parameterSize);
  1907. #endif
  1908.  
  1909.             DownLeft (parameter, parameterSize);
  1910.  
  1911.             HashThreeItems (checkValue, securitySize,
  1912.                     checkValue, securitySize,
  1913.                     branchVerifiers, securitySize,
  1914.                     parameter, parameterSize,
  1915.                     hashMethod);
  1916.         };
  1917.         path >>= 1;
  1918.         branchVerifiers += securitySize;
  1919.     };
  1920. }
  1921.  
  1922. /*
  1923.  * The following routine accepts as input a public key
  1924.  * (normally computed from a signature) and the name
  1925.  * of the public directory.  It looks up the public key
  1926.  * in the public directory.  It returns 0 if the search was
  1927.  * successful, and sets "userName" to the name found in
  1928.  * the public directory.  It returns non-zero if the search
  1929.  * was unsuccessful, and userName is left empty ("");
  1930.  *
  1931.  */
  1932. int 
  1933. LookUpPublicKey (publicKey, publicDirectoryName, userName)
  1934.     word32    publicKey[MAX_PUBLIC_KEY_SIZE]; /* Input */
  1935.     char    *publicDirectoryName;
  1936.     char    userName[MAX_USER_NAME_SIZE_IN_BYTES]; /* Output */
  1937. {    char    *publicFileName;
  1938.     word32    tempPublicKey[MAX_PUBLIC_KEY_SIZE];
  1939.     int     i;
  1940.     int    publicKeySize;
  1941.     int    scanReturnCode;
  1942.     FILE    *publicFile;
  1943.     char    *ownersName;
  1944.     char    tempName[MAX_USER_NAME_SIZE_IN_BYTES];
  1945.  
  1946.     /* open the "public file" entry, read only */
  1947.     publicFileName = MakePublicFileName(publicDirectoryName, publicKey);
  1948.     publicFile = fopen (publicFileName, "r");
  1949.     userName[0] = (char) 0;
  1950.     if (publicFile == NULL)
  1951.         return(-1);
  1952.     ownersName = FileOwnersName(publicFile);
  1953.     scanReturnCode = fscanf (publicFile,
  1954.         /* WARNING:
  1955.          * update constant 300 when MAX_USER_NAME_SIZE_IN_BYTES
  1956.          * is changed.  Updating this constant is required
  1957.          * to correctly prevent overflow if the public file
  1958.          * has a name which is too long.
  1959.          */
  1960.         "%*[^#]#%300[^:]: %lx", tempName, tempPublicKey);
  1961.     if (scanReturnCode == 0) /*  didn't scan the "#" */
  1962.         scanReturnCode = fscanf (publicFile,
  1963.             /* WARNING: update constant 300 when
  1964.              * MAX_USER_NAME_SIZE_IN_BYTES is changed.
  1965.              */
  1966.             "#%300[^:]: %lx", tempName, tempPublicKey);
  1967.     if(scanReturnCode != 2)
  1968.         return(-1);
  1969.     publicKeySize = ComputePublicKeySize(tempPublicKey);
  1970.     for (i = 1; i < publicKeySize; i++) {
  1971.         scanReturnCode = fscanf(publicFile, " %lx", &tempPublicKey[i]);
  1972.         if (scanReturnCode != 1)
  1973.             return(-1);
  1974.         };
  1975.     for (i = 0; i < publicKeySize; i++)
  1976.         if (publicKey[i] != tempPublicKey[i])
  1977.             return(-1);
  1978.     FileClose (publicFile, publicFileName);
  1979.     if ( (strlen(tempName)+strlen(ownersName)) >=
  1980.         MAX_USER_NAME_SIZE_IN_BYTES-4) {
  1981.         fprintf(stderr,
  1982.             "String: \"%s:%s\" is longer than %d bytes\n",
  1983.             ownersName, tempName, MAX_USER_NAME_SIZE_IN_BYTES);
  1984.         ErrAbort("");
  1985.     };
  1986.     strcpy(userName, ownersName);
  1987.     strcat(userName, ":");
  1988.     strcat(userName, tempName);
  1989.     return(0);
  1990. }
  1991.  
  1992. /*
  1993.  * The following routine creates/checks a one-time signature.  Note
  1994.  * that the routine can be used both to sign and to check a value to
  1995.  * sign.
  1996.  */
  1997. void 
  1998. OneTimeSignCheck (valueToSign, securitySize,
  1999.           parameter, parameterSize, signCheckFlag,
  2000.           noOfCounts, bitsPerVerifier,
  2001.           xyVector, hashForSignature, hashMethod)
  2002.     word32 valueToSign[ /* securitySize */ ];
  2003.     int     securitySize;
  2004.     word32 parameter[MAX_PARAMETER_SIZE];
  2005.     int     parameterSize;
  2006.     int     signCheckFlag;
  2007.     word32 xyVector[MAX_NO_OF_COUNTS * MAX_SECURITY_SIZE];
  2008.     word32 hashForSignature[MAX_SECURITY_SIZE];
  2009.     int     hashMethod;
  2010. {    int     i, j;
  2011.     word32    count[MAX_NO_OF_COUNTS];
  2012.     word32    twoToTheBitsPerVerifier;
  2013.     int     bitsNeeded;
  2014.     word32    parameterLastWord;
  2015.  
  2016.     twoToTheBitsPerVerifier = 1;
  2017.     twoToTheBitsPerVerifier <<= bitsPerVerifier;
  2018.  
  2019.  
  2020.     /* compute the counts  */
  2021.     for (i = 0; i < noOfCounts; i++)
  2022.         count[i] =
  2023.             FetchBits (valueToSign, securitySize,
  2024.                    i * bitsPerVerifier, bitsPerVerifier);
  2025.  
  2026.  
  2027.     /*
  2028.      * The valueToSign has some bits in it.  We need to pad out this
  2029.      * array with a "check" field to prevent tampering with the count
  2030.      * values by evil doers
  2031.      */
  2032.     FillInTheCheckField (count, noOfCounts,
  2033.                  securitySize, bitsPerVerifier,
  2034.                  twoToTheBitsPerVerifier);
  2035.     /*
  2036.      * Okay, we've spread the bits out into the array "count" and also
  2037.      * added the check field to the array "count"
  2038.      */
  2039.     /*
  2040.      * Compute the number of bits needed for the combined count and the
  2041.      * bitsPerVerifier in the parameter
  2042.      */
  2043.     bitsNeeded = SizeInBits ((word32)
  2044.                  noOfCounts * twoToTheBitsPerVerifier);
  2045.     /* and make room for that many bits in the parameter */
  2046.     for (i = 0; i < bitsNeeded; i++)
  2047.         UpRight (parameter, parameterSize);
  2048.     /*
  2049.      * Remember the last word of the parameter -- we diddle it to
  2050.      * parameterize each application of hashN for the one time signature
  2051.      */
  2052.     parameterLastWord = parameter[parameterSize - 1];
  2053.     /* zero out the hash value result for the signature  */
  2054.     for (i = 0; i < securitySize; i++)
  2055.         hashForSignature[i] = 0;
  2056.     for (i = 0; i < noOfCounts; i++) {
  2057.         /* hash down the sequence */
  2058.         if (signCheckFlag != CHECK) {
  2059.             for (j = twoToTheBitsPerVerifier - 1;
  2060.                     j > count[i]; j--) {
  2061.                 /* tweak the parameter for <i,j> */
  2062.                 parameter[parameterSize - 1] =
  2063.                     parameterLastWord ^
  2064.                     (i * twoToTheBitsPerVerifier + j);
  2065.                 HashTwoItems (&xyVector[i * securitySize],
  2066.                     securitySize,
  2067.                     &xyVector[i * securitySize],
  2068.                     securitySize,
  2069.                     parameter, parameterSize,
  2070.                     hashMethod);
  2071.             };
  2072.         };
  2073.         /* keep hashing  */
  2074.         if (signCheckFlag != SIGN) {
  2075.             for (j = count[i]; j > 0; j--) {
  2076.                 parameter[parameterSize - 1] =
  2077.                     parameterLastWord ^
  2078.                     (i * twoToTheBitsPerVerifier + j);
  2079.                 HashTwoItems (&xyVector[i * securitySize],
  2080.                     securitySize,
  2081.                     &xyVector[i * securitySize],
  2082.                     securitySize,
  2083.                     parameter, parameterSize,
  2084.                     hashMethod);
  2085.             };
  2086.             parameter[parameterSize - 1] = parameterLastWord ^
  2087.                 (i * twoToTheBitsPerVerifier);
  2088.             HashThreeItems (hashForSignature, securitySize,
  2089.                     hashForSignature, securitySize,
  2090.                     &xyVector[i * securitySize],
  2091.                     securitySize,
  2092.                     parameter, parameterSize,
  2093.                     hashMethod);
  2094.         };
  2095.     };
  2096.     /* Restore the parameter  */
  2097.     parameter[parameterSize - 1] = parameterLastWord;
  2098.     for (i = 0; i < bitsNeeded; i++)
  2099.         DownLeft (parameter, parameterSize);
  2100. }
  2101.  
  2102.  
  2103. /*
  2104.  * The following routine hashes the input file, compares this
  2105.  * with the hash stored in the signature (to verify they are
  2106.  * equal), then re-computes the public key using the provided
  2107.  * authentication information, and finally returns the computed
  2108.  * public key.
  2109.  */
  2110. Check(inputFile, sigFile, publicKey, dateTime32Ptr, msgBuffer)
  2111.     FILE    *inputFile;
  2112.     FILE    *sigFile;
  2113.     word32    publicKey[MAX_PUBLIC_KEY_SIZE];
  2114.     word32    *dateTime32Ptr;
  2115.     char    msgBuffer[MAX_MESSAGE_SIZE_IN_BYTES];
  2116. {    int     location;
  2117.     word32    pathDescription;
  2118.     int     signatures;
  2119.     word32    outputCheckValue[MAX_SECURITY_SIZE];
  2120.     int     hashMethod;
  2121.     int     securitySize;
  2122.     int     hashValueSize;
  2123.     word32    hashValue[MAX_HASH_VALUE_SIZE];
  2124.     int     noOfCounts;
  2125.     int     noOfSignatures;
  2126.     int     noOfBitsPerVerifier;
  2127.     word32    parameter[MAX_PARAMETER_SIZE];
  2128.     word32    checkValue[MAX_SECURITY_SIZE];
  2129.     int     parameterSize;
  2130.     word32    signature[MAX_SIGNATURE_SIZE];
  2131.     int    i;
  2132.     word32    hashFromSig[MAX_HASH_VALUE_SIZE];
  2133.     word32    *hashPtr;
  2134.     int    chunkSize;
  2135.     word32    wordsToHash;
  2136.     int    binaryDataFieldSize;
  2137. #if SHOW_TIMES
  2138.     word32    startTime, stopTime;
  2139.     int    signRepeatIndex;
  2140.     double    signTime;
  2141. #endif
  2142.  
  2143.     /* self-test, to make sure everything is okay.  */
  2144.     DoSelfTest (SELF_TEST);
  2145.     /* Check the digitally signed message  */
  2146.  
  2147. #if SHOW_TIMES
  2148.     startTime = GetCpuTime();
  2149.     for(signRepeatIndex=0; signRepeatIndex<1000; signRepeatIndex++) {
  2150. #endif
  2151.     ReadSignature (sigFile, &hashMethod,
  2152.             &noOfSignatures, parameter, ¶meterSize,
  2153.             &securitySize, &hashValueSize, &noOfCounts,
  2154.             &noOfBitsPerVerifier, signature, &location,
  2155.             &wordsToHash, hashFromSig, dateTime32Ptr,
  2156.             &binaryDataFieldSize, msgBuffer);
  2157.  
  2158.     HashFile (inputFile, hashValue, hashValueSize, hashMethod);
  2159.     for (i=0; i<hashValueSize; i++)
  2160.         if (hashValue[i] != hashFromSig[i])
  2161.             ErrAbort("File or signature has been changed");
  2162.     hashPtr = signature;
  2163.     for (i=0; i<hashValueSize; i++) hashValue[i] = 0;
  2164.     i = wordsToHash;
  2165.     chunkSize = INPUT_BLOCK_SIZE-hashValueSize;
  2166.     while (i >= chunkSize) {
  2167.         HashTwoItems(hashValue, hashValueSize,
  2168.             hashValue, hashValueSize,
  2169.             hashPtr, chunkSize, hashMethod);
  2170.         hashPtr += chunkSize;
  2171.         i -= chunkSize;
  2172.     };
  2173.     if (i>0)  HashTwoItems(hashValue, hashValueSize,
  2174.             hashValue, hashValueSize,
  2175.             hashPtr, i, hashMethod);
  2176.     HashTwoItems(hashValue, hashValueSize,
  2177.         hashValue, hashValueSize,
  2178.         &wordsToHash, 1, hashMethod);
  2179. #if DEBUG
  2180.     PrintIt ("hashValue=", hashValue, hashValueSize);
  2181.     PrintIt ("parameter=", parameter, parameterSize);
  2182. #endif
  2183.     /* initialize checkValue */
  2184.     HashTwoItems (checkValue, securitySize,
  2185.               hashValue, hashValueSize,
  2186.               parameter, parameterSize,
  2187.               hashMethod);
  2188.     for (signatures = 0; signatures < noOfSignatures; signatures++) {
  2189.         /* Set parameter for one-time signature  */
  2190.         DownLeft (parameter, parameterSize);
  2191.         UpLeft (parameter, parameterSize);
  2192. #if DEBUG
  2193.         printf ("\nAbout to check one time signature\n");
  2194.         PrintIt ("checkValue=", checkValue, securitySize);
  2195.         PrintIt ("parameter=", parameter, parameterSize);
  2196. #endif
  2197.         OneTimeSignCheck (checkValue, securitySize,
  2198.                   parameter, parameterSize, CHECK,
  2199.                   noOfCounts, noOfBitsPerVerifier,
  2200.              &signature[location], outputCheckValue, hashMethod);
  2201.         Copy (checkValue, outputCheckValue, securitySize);
  2202. #if DEBUG
  2203.         printf ("\nfinished checking one time signature\n");
  2204.         PrintIt ("checkValue=", checkValue, securitySize);
  2205.         PrintIt ("parameter=", parameter, parameterSize);
  2206. #endif
  2207.         location += securitySize * noOfCounts;
  2208.         pathDescription = signature[location];
  2209.         location++;    /* skip the path description */
  2210.         DownRight (parameter, parameterSize);
  2211.         CheckAuthenticationPath (checkValue, securitySize, parameter,
  2212.                      parameterSize, hashMethod,
  2213.                      pathDescription, &signature[location]);
  2214.         /* now skip past the authentication path */
  2215.         location -= securitySize;    /* fix off-by-one error */
  2216.         while (pathDescription != 0) {
  2217.             pathDescription >>= 1;
  2218.             location += securitySize;
  2219.         };
  2220.     };
  2221. #if SHOW_TIMES
  2222.      };
  2223.     stopTime = GetCpuTime();
  2224.     signTime = stopTime-startTime;
  2225.     signTime = signTime/1.0e6;
  2226.     fprintf(stderr, "%9.3f milliseconds to read and check signature\n",
  2227.         signTime);
  2228. #endif
  2229. #if DEBUG
  2230.     printf ("about to print results\n");
  2231.     PrintIt ("checkValue=", checkValue, securitySize);
  2232.     PrintIt ("parameter=", parameter, parameterSize);
  2233. #endif
  2234. #if SHOW_TIMES
  2235.     startTime = GetCpuTime();
  2236.     for(signRepeatIndex=0; signRepeatIndex<1000; signRepeatIndex++) {
  2237. #endif
  2238.     publicKey[0] = signature[0];
  2239.     Copy(&publicKey[1], checkValue, securitySize);
  2240.     Copy(&publicKey[1+securitySize], parameter, parameterSize);
  2241. #if SHOW_TIMES
  2242.      };
  2243.     stopTime = GetCpuTime();
  2244.     signTime = stopTime-startTime;
  2245.     signTime = signTime/1.0e6;
  2246.     fprintf(stderr, "%9.3f milliseconds for look up in public file\n",
  2247.         signTime);
  2248. #endif
  2249. }
  2250.  
  2251. /*
  2252.  * The following routine dumps a signature in a readable format.
  2253.  */
  2254. void 
  2255. DumpSig(sigFile)
  2256.     FILE    *sigFile;
  2257. {    int     location;
  2258.     word32    pathDescription;
  2259.     int     signatures;
  2260.     int     hashMethod;
  2261.     int     securitySize;
  2262.     int     hashValueSize;
  2263.     int     noOfCounts;
  2264.     int     noOfSignatures;
  2265.     int     noOfBitsPerVerifier;
  2266.     word32    parameter[MAX_PARAMETER_SIZE];
  2267.     int     parameterSize;
  2268.     word32    signature[MAX_SIGNATURE_SIZE];
  2269.     int    i;
  2270.     int    j;
  2271.     word32    dateTime32;
  2272.     char    message[MAX_MESSAGE_SIZE_IN_BYTES];
  2273.     word32    hashFromSig[MAX_HASH_VALUE_SIZE];
  2274.     word32    wordsToHash;
  2275.     int    binaryDataFieldSize;
  2276.     long    longTemp;
  2277.     char    dateString[80];
  2278.  
  2279.     ReadSignature (sigFile, &hashMethod,
  2280.             &noOfSignatures, parameter, ¶meterSize,
  2281.             &securitySize, &hashValueSize, &noOfCounts,
  2282.             &noOfBitsPerVerifier, signature, &location,
  2283.             &wordsToHash, hashFromSig, &dateTime32,
  2284.             &binaryDataFieldSize, message);
  2285.  
  2286.     printf(" hash method             = %d\n", hashMethod);
  2287.     printf(" number of counts        = %d\n", noOfCounts);
  2288.     printf(" no of bits per verifier = %d\n", noOfBitsPerVerifier);
  2289.     printf(" number of signatures    = %d\n", noOfSignatures);
  2290.     printf(" location of first sig   = %d\n", location);
  2291.     longTemp = dateTime32;
  2292.     strcpy(dateString, ctime(&longTemp));
  2293.     if (dateString[strlen(dateString)-1] == '\n')
  2294.         dateString[strlen(dateString)-1] = (char) 0;
  2295.     printf(" date of signature       = %s\n", dateString);
  2296.     printf(" message                 = \"%s\"\n", message);
  2297.     printf(" words to hash           = %d\n", wordsToHash);
  2298.     printf(" binary data field size  = %d\n", binaryDataFieldSize);
  2299.     printf(" security size           = %d\n", securitySize);
  2300.     printf(" parameter size          = %d\n", parameterSize);
  2301.     printf(" parameter               =");
  2302.     for (i=0; i<parameterSize; i++)
  2303.         printf(" %08lx", parameter[i]);
  2304.     printf("\n hash value size         = %d\n", hashValueSize);
  2305.     printf(" hash value              =");
  2306.     for (i=0; i<hashValueSize; i++)
  2307.         printf(" %08lx", hashFromSig[i]);
  2308.     printf("\n\n");
  2309.     
  2310.  
  2311.     for (signatures = 0; signatures < noOfSignatures; signatures++) {
  2312.         printf("\n authenticators:\n");
  2313.         for (i=0; i<noOfCounts; i++) {
  2314.             printf("          ");
  2315.             for (j=0; j<securitySize; j++) {
  2316.                 printf(" %08lx",
  2317.                     signature[location+i*securitySize+j]);
  2318.             };
  2319.             printf("\n");
  2320.         };
  2321.         location += securitySize * noOfCounts;
  2322.         pathDescription = signature[location];
  2323.         printf("\n path description        = %08lx\n", pathDescription);
  2324.         location++;    /* skip the path description */
  2325.         /* now skip past the authentication path */
  2326.         if (pathDescription != 0) while (pathDescription != 1) {
  2327.             printf("     ");
  2328.             for (i=0; i<securitySize; i++)
  2329.                 printf(" %08lx", signature[location+i]);
  2330.             printf("\n");
  2331.             pathDescription >>= 1;
  2332.             location += securitySize;
  2333.         };
  2334.     };
  2335. }
  2336.  
  2337.  
  2338.  
  2339. /* The signing routines follow this point  */
  2340.  
  2341.  
  2342. /* The following routine emptys the signature buffer  */
  2343. /* All it does is set the "next available word" pointer  */
  2344. /* to 0 */
  2345. void 
  2346. EmptySignatureBuffer (sigBuffer)
  2347.     struct SIG_BUF *sigBuffer;
  2348. {
  2349.     sigBuffer->locInSignature = 0;
  2350. }
  2351.  
  2352. /* Places the passed in array into the signature buffer.  */
  2353. void 
  2354. PutInSignatureBuffer (array, size, sigBuffer)
  2355.     word32 array[];
  2356.     int     size;
  2357.     struct SIG_BUF *sigBuffer;
  2358. {    int     i;
  2359.  
  2360.     if (sigBuffer->locInSignature + size >= MAX_SIGNATURE_SIZE)
  2361.         ErrAbort (" overflow of authentication path");
  2362.     for (i = 0; i < size; i++)
  2363.         sigBuffer->signature[sigBuffer->locInSignature + i] = array[i];
  2364.     sigBuffer->locInSignature += size;
  2365. }
  2366.  
  2367. void 
  2368. GenPathForOTT (depth, top, securitySize, noOfCounts,
  2369.         path, countVerifiers,
  2370.         authPathValues,
  2371.         sigBuffer)
  2372.     int     depth;
  2373.     int     top;
  2374.     int     securitySize;
  2375.     int     noOfCounts;
  2376.     word32 path[MAX_STACK_DEPTH];
  2377.     word32 countVerifiers
  2378.         [MAX_STACK_DEPTH]
  2379.         [MAX_NO_OF_COUNTS]
  2380.         [MAX_SECURITY_SIZE];
  2381.     word32 authPathValues
  2382.         [MAX_STACK_DEPTH]
  2383.         [2 * MAX_OTT_SIZE]
  2384.         [MAX_SECURITY_SIZE];
  2385.     struct SIG_BUF *sigBuffer;
  2386. {    int     i;
  2387.     word32 temp;
  2388.  
  2389.     /* spit out the count verifiers  */
  2390.     if (depth < top)
  2391.         for (i = 0; i < noOfCounts; i++) {
  2392. #if DEBUG
  2393.             PrintIt ("countVerifier=",
  2394.                  countVerifiers[depth + 1][i], securitySize);
  2395. #endif
  2396.             PutInSignatureBuffer (countVerifiers[depth + 1][i],
  2397.                           securitySize, sigBuffer);
  2398.         };
  2399.  
  2400.     /* and the path description */
  2401. #if DEBUG
  2402.     PrintIt ("path=", &path[depth], 1);
  2403. #endif
  2404.     PutInSignatureBuffer (&path[depth], 1, sigBuffer);
  2405.  
  2406.     /* and then the authentication path */
  2407.     temp = path[depth];
  2408.     for (temp = path[depth]; temp != 1; temp >>= 1) {
  2409. #if DEBUG
  2410.         PrintIt ("authPathValue=",
  2411.            authPathValues[depth][temp ^ 1], securitySize);
  2412. #endif
  2413.         PutInSignatureBuffer (authPathValues[depth][temp ^ 1],
  2414.                       securitySize, sigBuffer);
  2415.     };
  2416. }
  2417.  
  2418. void 
  2419. GenerateAuthenticationPath (top, securitySize,
  2420.                 noOfCounts,
  2421.                 path, countVerifiers,
  2422.                 authPathValues, sigBuffer)
  2423.     int     top;
  2424.     int     securitySize;
  2425.     int     noOfCounts;
  2426.     word32 path[MAX_STACK_DEPTH];
  2427.     word32 countVerifiers
  2428.         [MAX_STACK_DEPTH]
  2429.         [MAX_NO_OF_COUNTS]
  2430.         [MAX_SECURITY_SIZE];
  2431.     word32 authPathValues
  2432.         [MAX_STACK_DEPTH]
  2433.         [2 * MAX_OTT_SIZE]
  2434.         [MAX_SECURITY_SIZE];
  2435.     struct SIG_BUF *sigBuffer;
  2436. {    int     depth;
  2437.     for (depth = top; depth >= 0; depth--)
  2438.         GenPathForOTT (depth,
  2439.                 top, securitySize,
  2440.                 noOfCounts, path,
  2441.                countVerifiers, authPathValues, sigBuffer);
  2442. }
  2443.  
  2444. /*
  2445.  * Read in the information from the auxilliary file (which is stored
  2446.  * in binary) and convert it into some useful internal format.
  2447.  */
  2448. void 
  2449. ReadBinaryAuxInfo (top, securitySize, noOfCounts, OTTsize, authPathValues,
  2450.     countVerifiers, toggle)
  2451.     int     top;
  2452.     int    securitySize;
  2453.     int    noOfCounts;
  2454.     int    OTTsize;
  2455.     word32    authPathValues
  2456.         [MAX_STACK_DEPTH]
  2457.         [2 * MAX_OTT_SIZE]
  2458.         [MAX_SECURITY_SIZE];
  2459.     word32    countVerifiers
  2460.         [MAX_STACK_DEPTH]
  2461.         [MAX_NO_OF_COUNTS]
  2462.         [MAX_SECURITY_SIZE];
  2463.     int    toggle;
  2464. {    int    readReturnCode;
  2465.     FILE    *auxInfoFile;
  2466.     int    i,j,k,loc;
  2467.     word32    temp[MAX_STACK_DEPTH*MAX_SECURITY_SIZE*2*MAX_OTT_SIZE];
  2468.  
  2469.  
  2470.     if (2*MAX_OTT_SIZE < MAX_NO_OF_COUNTS)
  2471.         ErrAbort("2*MAX_OTT_SIZE < MAX_NO_OF_COUNTS");
  2472.     RangeCheck (top, 0, MAX_STACK_DEPTH - 1, "top");
  2473.     auxInfoFile = fopen (AuxInfoFile(toggle), "rb");
  2474.     if (auxInfoFile == NULL)
  2475.         ErrAbort ("Can't open aux info file for read");
  2476.     readReturnCode = fread((char*)temp, 1,
  2477.         top*noOfCounts*securitySize*sizeof(word32), auxInfoFile);
  2478.     if (readReturnCode !=
  2479.         top*noOfCounts*securitySize*sizeof(word32)) {
  2480.         fprintf(stderr,
  2481.             "Can't read verifiers from %s\n", AuxInfoFile(toggle));
  2482.         exit(1);
  2483.     };
  2484.     loc = 0;
  2485.     for(i=1; i<=top; i++)
  2486.     for(j=0; j<noOfCounts; j++)
  2487.     for(k=0; k<securitySize; k++)
  2488.         countVerifiers[i][j][k] = temp[loc++];
  2489.  
  2490.  
  2491.     readReturnCode = fread((char*)temp, 1,
  2492.         (top+1)*2*OTTsize*securitySize*sizeof(word32), auxInfoFile);
  2493.     if (readReturnCode!=
  2494.         (top+1)*2*OTTsize*securitySize*sizeof(word32)) {
  2495.         fprintf(stderr,
  2496.             "Can't read authPathValues from %s\n",
  2497.                 AuxInfoFile(toggle));
  2498.         exit(1);
  2499.     };
  2500.     loc = 0;
  2501.     for(i=0; i<=top; i++)
  2502.     for(j=0; j<2*OTTsize; j++)
  2503.     for(k=0; k<securitySize; k++)
  2504.          authPathValues[i][j][k] = temp[loc++];
  2505.  
  2506.     FileClose(auxInfoFile, AuxInfoFile(toggle));
  2507. }
  2508.  
  2509. /* Generate pseudo-random "secret X values" and put them into
  2510.  * "xyVector".  The number of elements in "xyVector" is given
  2511.  * by "elementsInXVector", while the size of each element
  2512.  * (which will typically be 2, the normal size for securitySize)
  2513.  * is given by "sizeOfXYElementInWords".  The two inputs, "bits1"
  2514.  * and "bits2" hold the "seed" information from which to generate
  2515.  * the pseudo-random secret X values.
  2516.  */
  2517. void 
  2518. GenerateSecretXValues (
  2519.                xyVector, elementsInXVector, sizeOfXYElementInWords,
  2520.                bits1, sizeOfBits1,
  2521.                bits2, sizeOfBits2,
  2522.                hashMethod)
  2523.     word32 xyVector[MAX_NO_OF_COUNTS * MAX_SECURITY_SIZE];
  2524.     int     elementsInXVector;
  2525.     int     sizeOfXYElementInWords;
  2526.     word32 bits1[];
  2527.     int     sizeOfBits1;
  2528.     word32 bits2[];
  2529.     int     sizeOfBits2;
  2530.     int     hashMethod;
  2531. {    int     i;
  2532.     word32 tempBlock[MAX_INPUT_BLOCK_SIZE];
  2533.  
  2534.     /*  Error checking  */
  2535.     if (sizeOfBits1+sizeOfBits2 > MAX_INPUT_BLOCK_SIZE)
  2536.         ErrAbort("Input size too large to generate xyVector");
  2537.     /* zero out the tempBlock bits  */
  2538.     for (i = 0; i < MAX_INPUT_BLOCK_SIZE; i++)
  2539.         tempBlock[i] = 0;
  2540.     /*  and copy the bits to tempBlock  */
  2541.     Copy( tempBlock,        bits1, sizeOfBits1);
  2542.     Copy(&tempBlock[sizeOfBits1],    bits2, sizeOfBits2);
  2543.     /*
  2544.      * generate some secret random bits by hashing together the input
  2545.      * bits, and putting them in xyVector.
  2546.      */
  2547.     HashExpand (xyVector, elementsInXVector * sizeOfXYElementInWords,
  2548.             tempBlock, sizeOfBits1+sizeOfBits2, hashMethod);
  2549. }
  2550.  
  2551.  
  2552. /*
  2553.  * The following routine takes a set of counts in the array "count,"
  2554.  * determines how big the "check" field should be, and how many elements near
  2555.  * the end of the "count" array it should occupy, computes the "check" field
  2556.  * and appends the needed bits to the end of "count"
  2557.  */
  2558. FillInTheCheckField (count, noOfCounts,
  2559.              securitySize, bitsPerVerifier,
  2560.              twoToTheBitsPerVerifier)
  2561.     word32 count[ /* noOfCounts */ ];
  2562.     int     noOfCounts;
  2563.     int     securitySize;
  2564.     int     bitsPerVerifier;
  2565.     word32 twoToTheBitsPerVerifier;
  2566. {    word32 sumOfCounts;
  2567.     word32 maxPossibleSumOfCounts;
  2568.     int     startOfCheckFieldInCountArray;
  2569.     int     sizeOfCheckFieldInBits;
  2570.     int     checkFieldCounts;
  2571.     int     startOfCheckFieldInBits;
  2572.     int     i;
  2573.  
  2574.     /*
  2575.      * figure out where the check field starts (the offset in the "count"
  2576.      * array)
  2577.      */
  2578.     startOfCheckFieldInCountArray =
  2579.         (WORD_SIZE_IN_BITS * securitySize - 1) / bitsPerVerifier + 1;
  2580.     /* compute the maximum possible sum of counts  */
  2581.     maxPossibleSumOfCounts = startOfCheckFieldInCountArray *
  2582.         (twoToTheBitsPerVerifier - 1);
  2583.     /*
  2584.      * figure out how many bits are in the check field by seeing how many
  2585.      * bits it takes to hold the maximum possible sum of counts
  2586.      */
  2587.     sizeOfCheckFieldInBits = SizeInBits (maxPossibleSumOfCounts);
  2588.     /* and figure out how many counts that takes  */
  2589.     checkFieldCounts = (sizeOfCheckFieldInBits - 1) / bitsPerVerifier + 1;
  2590.     /* make sure the check field will fit!  */
  2591.     if (startOfCheckFieldInCountArray + checkFieldCounts != noOfCounts)
  2592.         ErrAbort ("adjust noOfCounts");
  2593.  
  2594.     /* There shouldn't be anything in the check field right now  */
  2595.     for (i = startOfCheckFieldInCountArray; i < noOfCounts; i++)
  2596.         if (count[i] != 0)
  2597.             ErrAbort ("Undefined check field");
  2598.     /* add up the total value of the counts  */
  2599.     sumOfCounts = 0;
  2600.     for (i = 0; i < noOfCounts; i++)
  2601.         sumOfCounts += count[i];
  2602.     /* and reverse it  */
  2603.     sumOfCounts = maxPossibleSumOfCounts - sumOfCounts;
  2604.     /* figure out where the bits start  */
  2605.     startOfCheckFieldInBits = WORD_SIZE_IN_BITS -
  2606.             checkFieldCounts * bitsPerVerifier;
  2607.     /*
  2608.      * The following is not intrinsically wrong -- I'm just not going to
  2609.      * bother handling a check field bigger than 32 bits.  I figure it
  2610.      * should never happen....
  2611.      */
  2612.     if (startOfCheckFieldInBits <= 0)
  2613.         ErrAbort ("Check field overflowed 32 bits");
  2614.     /*
  2615.      * Okay, now we know the start and size of the "check" field, grab
  2616.      * the bits and put them into the "count" array at the proper spot
  2617.      */
  2618.     for (i = startOfCheckFieldInCountArray; i < noOfCounts; i++) {
  2619.         count[i] = FetchBits (&sumOfCounts, 1,
  2620.                   startOfCheckFieldInBits, bitsPerVerifier);
  2621.         startOfCheckFieldInBits += bitsPerVerifier;
  2622.     };
  2623.     if (startOfCheckFieldInBits < WORD_SIZE_IN_BITS)
  2624.         ErrAbort ("check field wouldn't fit");
  2625. }
  2626.  
  2627. /*  The following routine finishes an OTT (One Time Tree).  An
  2628.  *  OTT consists of several one-time signatures combined in a
  2629.  *  fixed-sized tree pattern by the use of one-way hash functions.
  2630.  *  (See, for example, "A Digital Signature Based on a Conventional
  2631.  *  Encryption Function" by Ralph C. Merkle, Crypto '87, page 369).
  2632.  *  This routine generates all of the needed one-time signatures, and
  2633.  *  computes the required hash value for the tree.  In addition, once
  2634.  *  the hash value for this OTT has been computed, the signature for
  2635.  *  the hash value, which must be generated using the appropriate
  2636.  *  one-time signature from the previous OTT, is also computed.
  2637.  */
  2638. void 
  2639. FinishNewOTT (
  2640.     top,
  2641.     securitySize,
  2642.     parameterSize,
  2643.     hashMethod,
  2644.     noOfCounts,
  2645.     noOfBitsPerVerifier,
  2646.     OTTsize,
  2647.     authPathValues,
  2648.     OTTparameterTop,
  2649.     countVerifiers,
  2650.     secretKey,
  2651.     secretKeySize
  2652. )
  2653.     int     top;
  2654.     int     securitySize;
  2655.     int     parameterSize;
  2656.     int     hashMethod;
  2657.     int     noOfCounts;
  2658.     int     noOfBitsPerVerifier;
  2659.     int    OTTsize;
  2660.     word32 authPathValues
  2661.         [MAX_STACK_DEPTH]
  2662.         [2 * MAX_OTT_SIZE]
  2663.         [MAX_SECURITY_SIZE];
  2664.     word32 OTTparameterTop[MAX_PARAMETER_SIZE];
  2665.     word32 countVerifiers
  2666.         [MAX_STACK_DEPTH]
  2667.         [MAX_NO_OF_COUNTS]
  2668.         [MAX_SECURITY_SIZE];
  2669.     word32 secretKey[SECRET_KEY_SIZE];
  2670.     int     secretKeySize;
  2671. {    word32 i, j;
  2672.     word32 parameter[MAX_PARAMETER_SIZE];
  2673.     word32 dummyValueToSign[MAX_SECURITY_SIZE];
  2674.     word32 throwAwayHashResult[MAX_SECURITY_SIZE];
  2675.     word32 xyVector[MAX_NO_OF_COUNTS * MAX_SECURITY_SIZE];
  2676.  
  2677.     for (i = 0; i < MAX_SECURITY_SIZE; i++)
  2678.         dummyValueToSign[i] = 0;
  2679.  
  2680.     /*
  2681.      * loop through for each one-time signature in the OTT and compute
  2682.      * its authentication value
  2683.      */
  2684.     for (i = OTTsize; i < 2 * OTTsize; i++) {
  2685.         Copy (parameter, OTTparameterTop, parameterSize);
  2686.         UpPath (parameter, parameterSize, i);
  2687.         UpLeft (parameter, parameterSize);
  2688.         /* generate the secret X values with which we sign things  */
  2689.         GenerateSecretXValues (xyVector, noOfCounts,
  2690.             securitySize,
  2691.             parameter, parameterSize,
  2692.             secretKey, secretKeySize,
  2693.             hashMethod);
  2694. #if DEBUG
  2695.         printf ("\ngenerating authPath value\n");
  2696.         PrintIt ("path=", &i, 1);
  2697.         PrintIt ("secretKey=", secretKey, secretKeySize);
  2698.         PrintIt ("xyVector[last]=",
  2699.              &xyVector[noOfCounts * securitySize - 1], 1);
  2700.         PrintIt ("parameter=", parameter, parameterSize);
  2701. #endif
  2702.         OneTimeSignCheck (dummyValueToSign, securitySize,
  2703.                   parameter, parameterSize, COMPUTE_OTT_HASH,
  2704.                   noOfCounts, noOfBitsPerVerifier,
  2705.                   xyVector, authPathValues[top][i], hashMethod);
  2706.  
  2707. #if DEBUG
  2708.         printf ("\done generating authPath value\n");
  2709.         PrintIt ("xyVector[last]=",
  2710.              &xyVector[noOfCounts * securitySize - 1], 1);
  2711.         PrintIt ("parameter=", parameter, parameterSize);
  2712.         PrintIt ("authPathValues[..]=",
  2713.                authPathValues[top][i], securitySize);
  2714. #endif
  2715.     };
  2716.  
  2717.     for (i = OTTsize - 1; i > 0; i--) {
  2718.         Copy (parameter, OTTparameterTop, parameterSize);
  2719.         UpPath (parameter, parameterSize, i);
  2720. #if DEBUG
  2721.         printf ("\ngenerating non-leaves in authPathValues\n");
  2722.         PrintIt ("path=", &i, 1);
  2723.         PrintIt ("parameter=", parameter, parameterSize);
  2724.         PrintIt ("authPathValues[top][2*path]=",
  2725.            authPathValues[top][2 * i], securitySize);
  2726.         PrintIt ("authPathValues[top][2*path+1]=",
  2727.              authPathValues[top][2 * i + 1],
  2728.              securitySize);
  2729. #endif
  2730.         HashThreeItems (
  2731.             authPathValues[top][i], securitySize,
  2732.             authPathValues[top][2 * i], securitySize,
  2733.             authPathValues[top][2 * i + 1], securitySize,
  2734.             parameter, parameterSize,
  2735.             hashMethod);
  2736.  
  2737. #if DEBUG
  2738.         printf ("\just-computed parent is:\n");
  2739.         PrintIt ("authPathValues[top][path]=",
  2740.                authPathValues[top][i], securitySize);
  2741. #endif
  2742.     };
  2743.  
  2744.     if (top > 0) {
  2745.         /*
  2746.          * gotta add the signature from the previous OTT to this
  2747.          * OTT
  2748.          */
  2749.         Copy (parameter, OTTparameterTop, parameterSize);
  2750.         DownLeft (parameter, parameterSize);
  2751.         UpLeft (parameter, parameterSize);
  2752.         /* generate the secret X values with which we sign things  */
  2753.         GenerateSecretXValues (xyVector, noOfCounts,
  2754.                 securitySize,
  2755.                 parameter, parameterSize,
  2756.                 secretKey, secretKeySize,
  2757.                 hashMethod);
  2758.  
  2759.         OneTimeSignCheck (authPathValues[top][1],
  2760.                 securitySize,
  2761.                 parameter, parameterSize, SIGN,
  2762.                 noOfCounts, noOfBitsPerVerifier,
  2763.                 xyVector, throwAwayHashResult,
  2764.                 hashMethod);
  2765.  
  2766.         for (i = 0; i < noOfCounts; i++)
  2767.             for (j = 0; j < securitySize; j++)
  2768.                 countVerifiers[top][i][j] =
  2769.                     xyVector[i * securitySize + j];
  2770.     };
  2771.  
  2772. }
  2773.  
  2774. /*
  2775.  * Write out the "aux Info" file in binary.  Convert the internal
  2776.  * information describing the signing "state" into a suitable binary
  2777.  * output format.  Note that the information in the auxilliary file
  2778.  * is not security sensitive, need not be kept secret, and can even
  2779.  * be modified.  If the information is modified, generated signatures
  2780.  * will be invalid (which will be rapidly detected) but security of
  2781.  * valid signatures will not be compromised.  Note that in principle
  2782.  * the incorrectly generated signatures could be repaired by determining
  2783.  * the correct authentication paths to use.
  2784.  */
  2785. void 
  2786. WriteBinaryAuxInfo(top, securitySize, noOfCounts, OTTsize, authPathValues,
  2787.     countVerifiers, toggle)
  2788.     int     top;
  2789.     int    securitySize;
  2790.     int    noOfCounts;
  2791.     int    OTTsize;
  2792.     word32    authPathValues
  2793.         [MAX_STACK_DEPTH]
  2794.         [2 * MAX_OTT_SIZE]
  2795.         [MAX_SECURITY_SIZE];
  2796.     word32    countVerifiers
  2797.         [MAX_STACK_DEPTH]
  2798.         [MAX_NO_OF_COUNTS]
  2799.         [MAX_SECURITY_SIZE];
  2800.     int    toggle;
  2801. {    FILE   *auxInfoFile;
  2802.     int    writeReturnCode;
  2803.     word32    temp[MAX_STACK_DEPTH*MAX_SECURITY_SIZE*2*MAX_OTT_SIZE];
  2804.     int    i,j,k,loc;
  2805.  
  2806.     if (2*MAX_OTT_SIZE < MAX_NO_OF_COUNTS)
  2807.         ErrAbort("2*MAX_OTT_SIZE < MAX_NO_OF_COUNTS");
  2808.     RangeCheck (top, 0, MAX_STACK_DEPTH - 1, "top");
  2809.     auxInfoFile = fopen (AuxInfoFile(toggle), "wb");
  2810.     if (auxInfoFile == NULL)
  2811.         ErrAbort ("Can't open aux info file for write");
  2812.     loc = 0;
  2813.     for(i=1; i<=top; i++)
  2814.     for(j=0; j<noOfCounts; j++)
  2815.     for(k=0; k<securitySize; k++)
  2816.         temp[loc++] = countVerifiers[i][j][k];
  2817.     writeReturnCode = fwrite((char*)temp, 1,
  2818.         top*noOfCounts*securitySize*sizeof(word32), auxInfoFile);
  2819.     if (writeReturnCode !=
  2820.         top*noOfCounts*securitySize*sizeof(word32)) {
  2821.         fprintf(stderr,
  2822.             "Can't write verifiers to %s\n", AuxInfoFile(toggle));
  2823.         exit(1);
  2824.     };
  2825.     loc = 0;
  2826.     for(i=0; i<=top; i++)
  2827.     for(j=0; j<2*OTTsize; j++)
  2828.     for(k=0; k<securitySize; k++)
  2829.         temp[loc++] = authPathValues[i][j][k];
  2830.     writeReturnCode = fwrite((char*)temp, 1,
  2831.         (top+1)*2*OTTsize*securitySize*sizeof(word32), auxInfoFile);
  2832.     if (writeReturnCode !=
  2833.         (top+1)*2*OTTsize*securitySize*sizeof(word32)) {
  2834.         fprintf(stderr,
  2835.             "Can't write authPathValues to %s\n",
  2836.                 AuxInfoFile(toggle));
  2837.         exit(1);
  2838.     };
  2839.     FileSyncAndClose(auxInfoFile, AuxInfoFile(toggle));
  2840. }
  2841.  
  2842. /*
  2843.  * Write out the signature buffer into the signature file.
  2844.  */
  2845. void 
  2846. WriteSignatureBuffer (sigFile, sigBuffer)
  2847.     FILE    *sigFile;
  2848.     struct    SIG_BUF *sigBuffer;
  2849. {    int     printCode;
  2850.     char    charSignature[MAX_SIGNATURE_SIZE * 4];
  2851.  
  2852.     /* write it!  */
  2853.     ConvertLongToChar (sigBuffer->signature, charSignature,
  2854.                sigBuffer->locInSignature);
  2855.     printCode = fwrite (charSignature, 4, sigBuffer->locInSignature,
  2856.                 sigFile);
  2857.     if (printCode != sigBuffer->locInSignature)
  2858.         ErrAbort ("can't write auth path to *.sig");
  2859. }
  2860.  
  2861. /*
  2862.  * The following routine simply generates some more-or-less random bits and
  2863.  * puts them into "randomOutput".
  2864.  * 
  2865.  * Notice that this routine is adequate ONLY IF "machineKey" IS NOT GOING TO
  2866.  * BE KEPT SECRET.  If "machineKey" is going to be kept secret, then a more
  2867.  * random method of generating random numbers is required here.
  2868.  * 
  2869.  * Whether or not to keep "machineKey" secret is a system design issue not
  2870.  * addressed here.  It will often be desirable to keep it secret.
  2871.  *
  2872.  * Many implementors will well wish to use a better "random number" generator
  2873.  * than hashing the time....
  2874.  */
  2875. void 
  2876. AssignRandom (randomOutput, sizeOfRandomOutputInWords,
  2877.           moreBits, sizeOfMoreBitsInWords)
  2878.     word32 randomOutput[];
  2879.     int     sizeOfRandomOutputInWords;
  2880.     word32 moreBits[];
  2881.     int     sizeOfMoreBitsInWords;
  2882. {    word32 unSignedTime;
  2883.  
  2884.     if (sizeOfRandomOutputInWords > 8)
  2885.         ErrAbort ("can't generate enough random bits");
  2886.     if (sizeOfRandomOutputInWords >
  2887.             (sizeOfMoreBitsInWords + SECRET_KEY_SIZE))
  2888.         ErrAbort ("too few input bits to generate random bits");
  2889.     unSignedTime = GetTime32();
  2890.     /*
  2891.      * hash together the time and whatever extra bits were passed in to
  2892.      * us
  2893.      */
  2894.     HashTwoItems (randomOutput, sizeOfRandomOutputInWords,
  2895.               moreBits, sizeOfMoreBitsInWords,
  2896.               &unSignedTime, 1, 4);
  2897.     /* randomOutput should now be reasonably random.  */
  2898. }
  2899.  
  2900. /*
  2901.  * Push an OTT (One Time Tree) onto the stack of One Time Trees.
  2902.  * Mostly, this is a housekeeping routine that pushes the stack,
  2903.  * initializes one or two critical variables in the OTT, and then
  2904.  * calles "FinishNewOTT".
  2905.  */
  2906. void 
  2907. PushOTT (
  2908.     topPtr,
  2909.     securitySize,
  2910.     parameterSize,
  2911.     hashMethod,
  2912.     noOfCounts,
  2913.     noOfBitsPerVerifier,
  2914.     path,
  2915.     authPathValues,
  2916.     OTTparameterTop,
  2917.     countVerifiers,
  2918.     secretKey,
  2919.     secretKeySize,
  2920.     OTTsize
  2921. )
  2922.     int    *topPtr;
  2923.     int     securitySize;
  2924.     int     parameterSize;
  2925.     int     hashMethod;
  2926.     int     noOfCounts;
  2927.     int     noOfBitsPerVerifier;
  2928.     word32 path[MAX_STACK_DEPTH];
  2929.     word32 authPathValues
  2930.         [MAX_STACK_DEPTH]
  2931.         [2 * MAX_OTT_SIZE]
  2932.         [MAX_SECURITY_SIZE];
  2933.     word32 OTTparameterTop[MAX_PARAMETER_SIZE];
  2934.     word32 countVerifiers
  2935.         [MAX_STACK_DEPTH]
  2936.         [MAX_NO_OF_COUNTS]
  2937.         [MAX_SECURITY_SIZE];
  2938.     word32 secretKey[SECRET_KEY_SIZE];
  2939.     int     secretKeySize;
  2940.     int    OTTsize;
  2941. {    UpPath (OTTparameterTop, parameterSize, path[*topPtr]);
  2942.     UpRight (OTTparameterTop, parameterSize);
  2943.     (*topPtr)++;
  2944.     if ((*topPtr) >= MAX_STACK_DEPTH)
  2945.         ErrAbort ("stack overflow");
  2946.  
  2947.     FinishNewOTT (*topPtr, securitySize,
  2948.         parameterSize, hashMethod,
  2949.         noOfCounts, noOfBitsPerVerifier,
  2950.         OTTsize, authPathValues,
  2951.         OTTparameterTop, countVerifiers,
  2952.         secretKey, secretKeySize);
  2953. }
  2954.  
  2955.  
  2956. /*
  2957.  * The following routine determines how much (if any) the stack of OTTs
  2958.  * should be allowed to grow.
  2959.  * 
  2960.  * The following method was chosen so that an infinite number of messages can be
  2961.  * signed while the depth (size) of the signature grows logarithmically. It
  2962.  * would also be possible to have this routine return a simple fixed constant
  2963.  * (like 4), in which case all signatures would have the same size (a stack
  2964.  * depth of 4) but the number of signatures would be fixed and finite.
  2965.  * 
  2966.  * This method of generating signatures also has the useful property that an OTT
  2967.  * can be generated once, used for a while, and then forgotten.  Other
  2968.  * methods of generating signatures (other patterns of signatures within the
  2969.  * tree) result in the need to periodically re-create OTTs.  While no great
  2970.  * burden, it seemed easier to avoid this situation.
  2971.  *
  2972.  * A small modification was made -- MIN_DEPTH is the minimum value that
  2973.  * this function will return.  This is useful when it is known that some
  2974.  * fixed number of messages will be signed, so there is no point in generating
  2975.  * very small signatures initially (with top = 0, say) when this
  2976.  * will simply force longer signatures later.
  2977.  * In other words, the tree of OTTs will
  2978.  * always have at least a certain depth (from the root OTT to the leaf OTT).
  2979.  */
  2980. int 
  2981. ComputeNewStackTop (top, path)
  2982.     int     top;
  2983.     word32 path[MAX_STACK_DEPTH];
  2984. {    int     i;
  2985.     int     newTop;
  2986.     int     bitsInPath;
  2987.     word32 signatureNumber;
  2988.     word32 signaturesAllowed;
  2989.     int     depthToAdd;
  2990.  
  2991.  
  2992.     /*
  2993.      * fancy computation basically determines how much stack depth to add
  2994.      * for the level we're looking at in the stack.
  2995.      * 
  2996.      * Example:  if the number of one-time signatures allowed per OTT is
  2997.      * always 32, then we want the following pattern for the first level:
  2998.      */
  2999.     /**
  3000.     32+0  <= path[0] < 32+16:    desired top: 0
  3001.     32+16 <= path[0] < 32+24:    desired top: 1
  3002.     32+24 <= path[0] < 32+28:    desired top: 2
  3003.     32+28 <= path[0] < 32+30:    desired top: 3
  3004.     32+30 <= path[0] < 32+31:    desired top: 4
  3005.     32+31  = path[0]        desired top: look at next level
  3006.     */
  3007.     /*
  3008.      * Note:  "path[0]" enumerates the leaves of this OTT (the one time
  3009.      * signatures) by encoding the first path as 32, the second path as
  3010.      * 33, etc. etc.  The last path is numbered 63.  There are a total of
  3011.      * 32 paths: numbered 32 to 63.
  3012.      * 
  3013.      */
  3014.  
  3015.     newTop = 0;
  3016.     for (i = 0; i <= top; i++) {
  3017.  
  3018.         /* Figure out where the top bit is */
  3019.         bitsInPath = SizeInBits (path[i]) - 1;
  3020.  
  3021.         /* Make a mask of just the top bit  */
  3022.         signaturesAllowed = (word32) 1 << bitsInPath;
  3023.  
  3024.         /* Now knock off the top bit  */
  3025.         signatureNumber = path[i] ^ signaturesAllowed;
  3026.  
  3027.         if (signatureNumber >= signaturesAllowed)
  3028.             ErrAbort ("logic error: sigNum >= sigsAllowed");
  3029.  
  3030.         /* And compute how much more depth to add to the stack  */
  3031.         depthToAdd = bitsInPath -
  3032.             SizeInBits (signaturesAllowed - signatureNumber - 1);
  3033.  
  3034.         if (depthToAdd < 0)
  3035.             ErrAbort ("logic error: depthToAdd < 0");
  3036.  
  3037.         newTop += depthToAdd;
  3038.  
  3039.         /*
  3040.          * If we're using the very last signature at this depth, we
  3041.          * need to look at the next depth to compute new top.
  3042.          * Otherwise, we know the value of newTop right now and
  3043.          * should return.
  3044.          */
  3045.         if (signaturesAllowed > signatureNumber + 1) {
  3046.             /*  force depth to MIN_DEPTH no matter what */
  3047.             if (newTop < MIN_DEPTH) newTop = MIN_DEPTH;
  3048.             return (newTop);
  3049.         }
  3050.     };
  3051.     /*  force depth to MIN_DEPTH no matter what */
  3052.     if (newTop < MIN_DEPTH) newTop = MIN_DEPTH;
  3053.     return (newTop);
  3054. }
  3055.  
  3056.  
  3057.  
  3058. /*
  3059.  * The following routine reads and hashes the input (taken from
  3060.  * "inputFile") and generates a valid signature for that hash.
  3061.  * The valid signature is written into the file: "sigFile".
  3062.  * The provided userKeyString is a secret key provided by the
  3063.  * user.  This user-provided secret key is combined with the
  3064.  * "machineKey" (which might or might not be secret, depending
  3065.  * on the desires of the particular user/site) to generate the
  3066.  * secretKey which is actually used to sign messages.
  3067.  * Much of the code is taken up
  3068.  * with the trivia of error checking, command-line parameter checking,
  3069.  * self-tests, and the like.
  3070.  * 
  3071.  */
  3072.  
  3073. void 
  3074. Sign (userKeyString, message, inputFile, sigFile)
  3075.     char    *userKeyString;
  3076.     char    message[MAX_MESSAGE_SIZE_IN_BYTES];
  3077.     FILE    *inputFile;
  3078.     FILE    *sigFile;
  3079. {    int     top;
  3080.     int     newStackTop;
  3081.     int     i;
  3082.     word32    parameter[MAX_PARAMETER_SIZE];
  3083.     word32    throwAwayHashResult[MAX_SECURITY_SIZE];
  3084.     word32    temp;
  3085.     int     updateAuxInfo;
  3086.     int     hashMethod;
  3087.     int     securitySize;
  3088.     int     hashValueSize;
  3089.     word32    hashValue[MAX_HASH_VALUE_SIZE];
  3090.     char    charUserKey[USER_KEY_SIZE_IN_BYTES];
  3091.     word32    userKey[USER_KEY_SIZE];
  3092.     word32    secretKey[SECRET_KEY_SIZE];
  3093.     word32    publicKey[MAX_PUBLIC_KEY_SIZE];
  3094.     word32    hashedUserKey[HASHED_USER_KEY_SIZE];
  3095.     word32    machineKey[MACHINE_KEY_SIZE];
  3096.     word32    authPathValues
  3097.             [MAX_STACK_DEPTH]
  3098.             [2 * MAX_OTT_SIZE]
  3099.             [MAX_SECURITY_SIZE];
  3100.     word32    countVerifiers
  3101.             [MAX_STACK_DEPTH]
  3102.             [MAX_NO_OF_COUNTS]
  3103.             [MAX_SECURITY_SIZE];
  3104.     word32    path[MAX_STACK_DEPTH];
  3105.     int     noOfCounts;
  3106.     int     noOfBitsPerVerifier;
  3107.     word32    rootParameter[MAX_PARAMETER_SIZE];
  3108.     word32    checkValue[MAX_SECURITY_SIZE];
  3109.     word32    root[MAX_SECURITY_SIZE];
  3110.     word32    xyVector[MAX_NO_OF_COUNTS * MAX_SECURITY_SIZE];
  3111.     int     parameterSize;
  3112.     struct    SIG_BUF sigBuffer[1];
  3113.     word32    tempHSC[HASHED_USER_KEY_SIZE];
  3114.     word32    dateTime32;
  3115.     word32    wordMessage[MAX_MESSAGE_SIZE];
  3116.     int    messageSize;
  3117.     int    messageSizeInBytes;
  3118.     word32    wordsToHash;
  3119.     word32    *hashPtr;
  3120.     word32    binaryDataFieldSize;
  3121.     int    startOfBinaryData;
  3122.     int    endOfBinaryData;
  3123.     int    chunkSize;
  3124.     char    file1Name[MAX_FILE_NAME_SIZE_IN_BYTES];
  3125.     char    file2Name[MAX_FILE_NAME_SIZE_IN_BYTES];
  3126.     FILE    *file1;
  3127.     FILE    *file2;
  3128.     int    toggle;
  3129.     int    OTTsize;
  3130. #if SHOW_TIMES
  3131.     word32    startTime, stopTime;
  3132.     int    signRepeatIndex;
  3133.     double    signTime;
  3134.     int    rememberedTop;
  3135. #endif
  3136.  
  3137.     /* self-test, to make sure everything is okay.  */
  3138.     DoSelfTest (SELF_TEST);
  3139.     strncpy(charUserKey, userKeyString, USER_KEY_SIZE_IN_BYTES);
  3140.     ConvertBytes (charUserKey, userKey, USER_KEY_SIZE_IN_BYTES);
  3141.     NameStableStorage(file1Name, file2Name);
  3142.     OpenAndLockTwoFiles(&file1, file1Name, &file2, file2Name);
  3143.     ReadStableStorage (file1, file2, machineKey, publicKey,
  3144.         hashedUserKey, path, &top, &toggle, &OTTsize);
  3145.     UnPackHeader (publicKey[0], &hashMethod,
  3146.             &securitySize, ¶meterSize,
  3147.             &noOfBitsPerVerifier, &hashValueSize, &noOfCounts);
  3148.     HashTwoItems(tempHSC, HASHED_USER_KEY_SIZE,
  3149.         userKey, USER_KEY_SIZE,
  3150.         userKey, USER_KEY_SIZE, hashMethod);
  3151.     for (i=0; i<20; i++) HashTwoItems(
  3152.                 tempHSC, HASHED_USER_KEY_SIZE,
  3153.                 tempHSC, HASHED_USER_KEY_SIZE,
  3154.                 tempHSC, HASHED_USER_KEY_SIZE,
  3155.                 hashMethod);
  3156.     for (i=0; i<HASHED_USER_KEY_SIZE; i++)
  3157.         if (tempHSC[i] != hashedUserKey[i])
  3158.             ErrAbort("Incorrect user key entered.");
  3159.     Copy(root, &publicKey[1], securitySize);
  3160.     Copy(rootParameter, &publicKey[1+securitySize], parameterSize);
  3161.     /*
  3162.      * Hash the user-provided key (presumed to be secret) and the
  3163.      * machine-readable key (security is enhanced if the machine key is
  3164.      * also secret.  If the machine key is not secret, it still serves a
  3165.      * useful, though less important, function).
  3166.      * 
  3167.      * The result is the "secretKey", from which all other secret
  3168.      * information is generated in a deterministic manner.
  3169.      */
  3170.  
  3171. #if DEBUG
  3172.     PrintIt ("machine key is:",
  3173.          machineKey, MACHINE_KEY_SIZE);
  3174.     PrintIt ("user key is:",
  3175.          userKey, USER_KEY_SIZE);
  3176. #endif
  3177.  
  3178.     HashTwoItems (secretKey, SECRET_KEY_SIZE,
  3179.               machineKey, MACHINE_KEY_SIZE,
  3180.               userKey, USER_KEY_SIZE,
  3181.               hashMethod);
  3182. #if DEBUG
  3183.     PrintIt ("Secret key for signing is:", secretKey, SECRET_KEY_SIZE);
  3184. #endif
  3185.     /* Generate the digital signature  */
  3186. #if SHOW_TIMES
  3187.     startTime = GetCpuTime();
  3188.     for(signRepeatIndex=0; signRepeatIndex<1000; signRepeatIndex++) {
  3189. #endif
  3190.     ReadBinaryAuxInfo (top, securitySize, noOfCounts,
  3191.         OTTsize, authPathValues,
  3192.         countVerifiers, toggle);
  3193. #if SHOW_TIMES
  3194.      };
  3195.     stopTime = GetCpuTime();
  3196.     signTime = stopTime-startTime;
  3197.     signTime = signTime/1.0e6;
  3198.     fprintf(stderr, "%9.3f milliseconds reading binary state\n",
  3199.         signTime);
  3200.     startTime = GetCpuTime();
  3201.     for(signRepeatIndex=0; signRepeatIndex<1000; signRepeatIndex++) {
  3202. #endif
  3203.  
  3204.     HashFile (inputFile, hashValue, hashValueSize, hashMethod);
  3205.  
  3206. #if SHOW_TIMES
  3207.      };
  3208.     stopTime = GetCpuTime();
  3209.     signTime = stopTime-startTime;
  3210.     signTime = signTime/1.0e6;
  3211.     fprintf(stderr, "%9.3f milliseconds hashing file\n",
  3212.         signTime);
  3213.     startTime = GetCpuTime();
  3214.     for(signRepeatIndex=0; signRepeatIndex<1000; signRepeatIndex++) {
  3215. #endif
  3216.     /* get the root parameter  */
  3217.     Copy (parameter, rootParameter, parameterSize);
  3218.  
  3219.     /*  push the root parameter up the authentication path */
  3220.     for (i=0; i <= top; i++) {
  3221.         UpPath (parameter, parameterSize, path[i]);
  3222.         UpRight (parameter, parameterSize);
  3223.         };
  3224.  
  3225.     /* spit out the head of the signature  */
  3226.     EmptySignatureBuffer (sigBuffer);
  3227.     PackHeader(&temp, hashMethod, securitySize,
  3228.         parameterSize, noOfBitsPerVerifier);
  3229.     PutInSignatureBuffer (&temp, 1, sigBuffer);
  3230.     if (top >= 255)
  3231.         ErrAbort ("Stack exceeds depth of 255");
  3232.     temp = top + 1;
  3233.     messageSizeInBytes = strlen(message)+1;
  3234.     messageSize = (messageSizeInBytes+3)>>2;
  3235.     binaryDataFieldSize = 1+hashValueSize+parameterSize;
  3236.     wordsToHash = 2+binaryDataFieldSize+messageSize;
  3237.     if ( (wordsToHash & 0xffff0000L) != 0)
  3238.         ErrAbort("message + stuff over 64 kilobytes.");
  3239.     temp |= (wordsToHash<<16);
  3240.     temp |= (binaryDataFieldSize << 8);
  3241.     PutInSignatureBuffer (&temp, 1, sigBuffer);
  3242.  
  3243.     startOfBinaryData = sigBuffer->locInSignature;
  3244. #if DEBUG
  3245.     PrintIt ("\n initial parameter=", parameter, parameterSize);
  3246. #endif
  3247.     dateTime32 = GetTime32();
  3248.     PutInSignatureBuffer (&dateTime32, 1, sigBuffer);
  3249.     PutInSignatureBuffer (hashValue, hashValueSize, sigBuffer);
  3250.     PutInSignatureBuffer (parameter, parameterSize, sigBuffer);
  3251. /*
  3252.  * Additional binary fields of data can be added at this point by
  3253.  * inserting additional calls to "PutInSignatureBuffer".  The additional
  3254.  * fields will be ignored by the signature checking program.  To inform
  3255.  * the signature checking program of the size of the additional fields,
  3256.  * it is necessary to increase the size of "binaryDataFieldSize" by the
  3257.  * appropriate amount.  It is computed above, and its value is checked
  3258.  * in the following two statements.
  3259.  */
  3260.     endOfBinaryData = sigBuffer->locInSignature;
  3261.     if ( (endOfBinaryData-startOfBinaryData) != binaryDataFieldSize)
  3262.         ErrAbort("error while generating size of binary data field");
  3263.     ConvertBytes(message, wordMessage, messageSizeInBytes);
  3264.     PutInSignatureBuffer (wordMessage, messageSize, sigBuffer);
  3265.     if (wordMessage[messageSize-1]&0xffL != 0)
  3266.         ErrAbort("wordMessage is not null terminated");
  3267.     hashPtr = sigBuffer->signature;
  3268.     for (i=0; i<hashValueSize; i++) hashValue[i] = 0;
  3269.     i = wordsToHash;
  3270.     chunkSize = INPUT_BLOCK_SIZE-hashValueSize;
  3271.     while (i >= chunkSize) {
  3272.         HashTwoItems(hashValue, hashValueSize,
  3273.             hashValue, hashValueSize,
  3274.             hashPtr, chunkSize, hashMethod);
  3275.         hashPtr += chunkSize;
  3276.         i -= chunkSize;
  3277.     };
  3278.     if (i>0)  HashTwoItems(hashValue, hashValueSize,
  3279.             hashValue, hashValueSize,
  3280.             hashPtr, i,hashMethod);
  3281.     HashTwoItems(hashValue, hashValueSize,
  3282.         hashValue, hashValueSize,
  3283.         &wordsToHash, 1, hashMethod);
  3284.     /*
  3285.      * hash the double-sized value produced by the strong hash function
  3286.      * into the smaller value that is actually signed.
  3287.      */
  3288. #if DEBUG
  3289.     printf ("SIGNING\n");
  3290.     PrintIt ("hashValue=", hashValue, hashValueSize);
  3291.     PrintIt ("parameter=", parameter, parameterSize);
  3292. #endif
  3293.     HashTwoItems (checkValue, securitySize,
  3294.               hashValue, hashValueSize,
  3295.               parameter, parameterSize,
  3296.               hashMethod);
  3297.     DownLeft (parameter, parameterSize);
  3298.     UpLeft (parameter, parameterSize);
  3299.     /* generate the secret X values with which we sign things  */
  3300.     GenerateSecretXValues (xyVector, noOfCounts, securitySize,
  3301.                    parameter, parameterSize,
  3302.                    secretKey, SECRET_KEY_SIZE, hashMethod);
  3303.  
  3304. #if DEBUG
  3305.     printf ("\nAbout to generate one time signature\n");
  3306.     PrintIt ("path=", &path[top], 1);
  3307.     PrintIt ("secretKey=", secretKey, SECRET_KEY_SIZE);
  3308.     PrintIt ("xyVector[last]=",
  3309.          &xyVector[noOfCounts * securitySize - 1], 1);
  3310.     PrintIt ("checkValue=", checkValue, securitySize);
  3311.     PrintIt ("parameter=", parameter, parameterSize);
  3312. #endif
  3313.  
  3314.     OneTimeSignCheck (checkValue, securitySize,
  3315.               parameter, parameterSize, SIGN,
  3316.               noOfCounts, noOfBitsPerVerifier,
  3317.               xyVector, throwAwayHashResult, hashMethod);
  3318.  
  3319. #if DEBUG
  3320.     printf ("\nfinished generating one time signature\n");
  3321.     PrintIt ("xyVector[last]=",
  3322.          &xyVector[noOfCounts * securitySize - 1], 1);
  3323.     PrintIt ("checkValue (discarded)=",
  3324.          throwAwayHashResult, securitySize);
  3325. #endif
  3326.     for (i = 0; i < noOfCounts; i++)
  3327.         PutInSignatureBuffer (&xyVector[i * securitySize],
  3328.                       securitySize, sigBuffer);
  3329.     GenerateAuthenticationPath (top, securitySize,
  3330.                     noOfCounts, path, countVerifiers,
  3331.                     authPathValues, sigBuffer);
  3332. #if SHOW_TIMES
  3333.      };
  3334.     stopTime = GetCpuTime();
  3335.     signTime = stopTime-startTime;
  3336.     signTime = signTime/1.0e6;
  3337.     fprintf(stderr, "%9.3f milliseconds generating signature\n",
  3338.         signTime);
  3339. #endif
  3340.     /*
  3341.      * make sure the aux info is updated in preparation for the next
  3342.      * signature
  3343.      */
  3344.     updateAuxInfo = FALSE;
  3345.     if (BumpPath (&path[top]) == PATHOVERFLOW) {
  3346.         updateAuxInfo = TRUE;
  3347.         /*
  3348.          * We've run out of signatures in the top OTT. Do Something!
  3349.          */
  3350.         while (BumpPath (&path[top]) == PATHOVERFLOW) {
  3351.             top--;
  3352.             if (top < 0)
  3353.                 ErrAbort ("Logic Error: no signatures");
  3354.         };
  3355.     };
  3356. #if SHOW_TIMES
  3357.     startTime = GetCpuTime();
  3358.     rememberedTop = top;
  3359.     for(signRepeatIndex=0; signRepeatIndex<1000; signRepeatIndex++) {
  3360.     top = rememberedTop;
  3361. #endif
  3362.     newStackTop = ComputeNewStackTop (top, path);
  3363.     if (newStackTop != top)
  3364.         updateAuxInfo = TRUE;
  3365. #if DEBUG
  3366.     printf ("\n new top= %d\n", newStackTop);
  3367. #endif
  3368.     /* get the root parameter  */
  3369.     Copy (parameter, rootParameter, parameterSize);
  3370.     /*  push the root parameter up the authentication path */
  3371.     for (i=0; i < top; i++) {
  3372.         UpPath (parameter, parameterSize, path[i]);
  3373.         UpRight (parameter, parameterSize);
  3374.         };
  3375.     while (top < newStackTop) {
  3376.         path[top+1] = OTTsize;
  3377.         PushOTT (&top, securitySize, parameterSize, hashMethod,
  3378.                noOfCounts, noOfBitsPerVerifier,
  3379.                path, authPathValues,
  3380.                parameter, countVerifiers,
  3381.                secretKey, SECRET_KEY_SIZE, OTTsize);
  3382.         };
  3383. #if SHOW_TIMES
  3384.      };
  3385.     stopTime = GetCpuTime();
  3386.     signTime = stopTime-startTime;
  3387.     signTime = signTime/1.0e6;
  3388.     fprintf(stderr, "%9.3f milliseconds setting up for next signature\n",
  3389.         signTime);
  3390.     startTime = GetCpuTime();
  3391.     for(signRepeatIndex=0; signRepeatIndex<1000; signRepeatIndex++) {
  3392. #endif
  3393.     if (updateAuxInfo == TRUE) {
  3394.         toggle ^= 1;
  3395.         WriteBinaryAuxInfo(top, securitySize,
  3396.             noOfCounts, OTTsize, authPathValues,
  3397.             countVerifiers, toggle);
  3398.     };
  3399.     /*
  3400.      * DON'T WRITE OUT THE SIGNATURE UNTIL AFTER UPDATING STABLE
  3401.      * STORAGE!!
  3402.      */
  3403.     WriteStableStorage (file1, file2, machineKey, publicKey,
  3404.             hashedUserKey, path, top, toggle, OTTsize);
  3405. #if SHOW_TIMES
  3406.      };
  3407.     stopTime = GetCpuTime();
  3408.     signTime = stopTime-startTime;
  3409.     signTime = signTime/1.0e6;
  3410.     fprintf(stderr, "%9.3f milliseconds writing stable storage\n",
  3411.         signTime);
  3412. #endif
  3413. /*  Hard to repeatedly close the file.... */
  3414.     FileSyncAndClose(file1, file1Name);
  3415.     FileSyncAndClose(file2, file2Name);
  3416. #if SHOW_TIMES
  3417.     startTime = GetCpuTime();
  3418.     for(signRepeatIndex=0; signRepeatIndex<1000; signRepeatIndex++) {
  3419. #endif
  3420.     WriteSignatureBuffer (sigFile, sigBuffer);
  3421. #if SHOW_TIMES
  3422.      };
  3423.     stopTime = GetCpuTime();
  3424.     signTime = stopTime-startTime;
  3425.     signTime = signTime/1.0e6;
  3426.     fprintf(stderr, "%9.3f milliseconds writing state and signature\n",
  3427.         signTime);
  3428. #endif
  3429. };
  3430.  
  3431. /* The following routine writes an entry to the public file.  It
  3432.  * is used during generation of the public key.  Note that the
  3433.  * "public file" is in fact a directory, and that the file names
  3434.  * in the directory are in fact derived from the public key
  3435.  * values, not from the user's name.  This is convenient for various
  3436.  * odd reasons that are idiosyncratic to this signature method.
  3437.  * Each public key gets its own file in the directory.  Note that
  3438.  * it is theoretically possible (but can be made arbitrarily
  3439.  * improbable) for two different public keys to have the same
  3440.  * file name in the public directory.  If this happens, it's just
  3441.  * tough.  You get an error message and are told to try again.
  3442.  * For those who find this offensive, the file name for the public
  3443.  * key could in fact encode the entire public key.  In this case,
  3444.  * a collsion in the directory would be as improbable as two
  3445.  * public keys being generated that were in fact identical.  This
  3446.  * probability can also be made as low as desired.
  3447.  */
  3448. void 
  3449. WriteEntryToPublicFile (publicDirectoryName, name, publicKey,
  3450.             secretKey, secretKeySize)
  3451.     char   *publicDirectoryName;
  3452.     char    name[];
  3453.     word32    publicKey[MAX_PUBLIC_KEY_SIZE];
  3454.     word32 secretKey[];
  3455.     int secretKeySize;
  3456. {    int     i;
  3457.     FILE   *descriptor;
  3458.     int     printReturnCode;
  3459.     int    publicKeySize;
  3460.     char    *publicFileName;
  3461.  
  3462.     /* open the "public file" entry for writing */
  3463.     publicFileName = MakePublicFileName(publicDirectoryName, publicKey);
  3464.     if (FileExists(publicFileName) == 0)
  3465.         ErrAbort("Highly improbable collision occured -- try again.");
  3466.     descriptor = fopen (publicFileName, "w");
  3467.     if (descriptor == NULL)
  3468.         ErrAbort ("Could not write entry to public file");
  3469.  
  3470.     printReturnCode = fprintf (descriptor, "#%s: %08lx",
  3471.         name, publicKey[0]);
  3472.     if (printReturnCode <= 0)
  3473.         ErrAbort ("bad write to public file");
  3474.  
  3475.     publicKeySize = ComputePublicKeySize(publicKey);
  3476.     for (i = 1; i < publicKeySize; i++) {
  3477.         printReturnCode = fprintf (descriptor,
  3478.                        " %08lx", publicKey[i]);
  3479.     if (printReturnCode <= 0)
  3480.         ErrAbort ("bad public key write to public file");
  3481.     };
  3482.  
  3483.     printReturnCode = fprintf (descriptor, "\n");
  3484.     if (printReturnCode <= 0)
  3485.         ErrAbort ("bad string write to public file");
  3486.     FileClose (descriptor, publicFileName);
  3487. };
  3488.  
  3489. /* The following routine is used to recover the auxilliary information
  3490.  * if it is damaged or lost.  The auxilliary information can be derived
  3491.  * from the information kept in stable storage.
  3492.  */
  3493. void
  3494. RecoverAuxInfo(userKeyString)
  3495.     char    *userKeyString;
  3496. {    int    top;
  3497.     int    newStackTop;
  3498.     int    i;
  3499.     int    hashMethod;
  3500.     int    securitySize;
  3501.     int    hashValueSize;
  3502.     char    charUserKey[USER_KEY_SIZE_IN_BYTES];
  3503.     word32    userKey[USER_KEY_SIZE];
  3504.     word32    secretKey[SECRET_KEY_SIZE];
  3505.     word32    publicKey[MAX_PUBLIC_KEY_SIZE];
  3506.     word32    hashedUserKey[HASHED_USER_KEY_SIZE];
  3507.     word32    machineKey[MACHINE_KEY_SIZE];
  3508.     word32    authPathValues
  3509.             [MAX_STACK_DEPTH]
  3510.             [2 * MAX_OTT_SIZE]
  3511.             [MAX_SECURITY_SIZE];
  3512.     word32    countVerifiers
  3513.             [MAX_STACK_DEPTH]
  3514.             [MAX_NO_OF_COUNTS]
  3515.             [MAX_SECURITY_SIZE];
  3516.     word32    path[MAX_STACK_DEPTH];
  3517.     int     noOfCounts;
  3518.     int     noOfBitsPerVerifier;
  3519.     word32    rootParameter[MAX_PARAMETER_SIZE];
  3520.     word32    root[MAX_SECURITY_SIZE];
  3521.     int     parameterSize;
  3522.     word32    tempHSC[HASHED_USER_KEY_SIZE];
  3523.     char    file1Name[MAX_FILE_NAME_SIZE_IN_BYTES];
  3524.     char    file2Name[MAX_FILE_NAME_SIZE_IN_BYTES];
  3525.     FILE    *file1;
  3526.     FILE    *file2;
  3527.     int    toggle;
  3528.     int    OTTsize;
  3529.  
  3530.     strncpy(charUserKey, userKeyString, USER_KEY_SIZE_IN_BYTES);
  3531.     ConvertBytes (charUserKey, userKey, USER_KEY_SIZE_IN_BYTES);
  3532.     NameStableStorage(file1Name, file2Name);
  3533.     OpenAndLockTwoFiles(&file1, file1Name, &file2, file2Name);
  3534.     ReadStableStorage (file1, file2, machineKey, publicKey,
  3535.         hashedUserKey, path, &newStackTop, &toggle, &OTTsize);
  3536.     UnPackHeader (publicKey[0], &hashMethod,
  3537.             &securitySize, ¶meterSize,
  3538.             &noOfBitsPerVerifier, &hashValueSize, &noOfCounts);
  3539.     HashTwoItems(tempHSC, HASHED_USER_KEY_SIZE,
  3540.         userKey, USER_KEY_SIZE,
  3541.         userKey, USER_KEY_SIZE, hashMethod);
  3542.     for (i=0; i<20; i++) HashTwoItems(
  3543.                 tempHSC, HASHED_USER_KEY_SIZE,
  3544.                 tempHSC, HASHED_USER_KEY_SIZE,
  3545.                 tempHSC, HASHED_USER_KEY_SIZE,
  3546.                 hashMethod);
  3547.     for (i=0; i<HASHED_USER_KEY_SIZE; i++)
  3548.         if (tempHSC[i] != hashedUserKey[i])
  3549.             ErrAbort("Incorrect user key entered.");
  3550.     Copy(root, &publicKey[1], securitySize);
  3551.     Copy(rootParameter, &publicKey[1+securitySize], parameterSize);
  3552.     /*
  3553.      * Hash the user-provided key (presumed to be secret) and the
  3554.      * machine-readable key (security is enhanced if the machine key is
  3555.      * also secret.  If the machine key is not secret, it still serves a
  3556.      * useful, though less important, function).
  3557.      * 
  3558.      * The result is the "secretKey", from which all other secret
  3559.      * information is generated in a deterministic manner.
  3560.      */
  3561.  
  3562.     HashTwoItems (secretKey, SECRET_KEY_SIZE,
  3563.               machineKey, MACHINE_KEY_SIZE,
  3564.               userKey, USER_KEY_SIZE,
  3565.               hashMethod);
  3566.     /* initialize the top (i.e. 0th) OTT  */
  3567.     top = 0;
  3568.     FinishNewOTT (top, securitySize, parameterSize, hashMethod,
  3569.             noOfCounts, noOfBitsPerVerifier, OTTsize,
  3570.             authPathValues, rootParameter, countVerifiers,
  3571.             secretKey, SECRET_KEY_SIZE);
  3572.     for (i=0; i<securitySize; i++)
  3573.         if(root[i] != authPathValues[0][1][i])
  3574.             ErrAbort("Recovery failed");
  3575.     while (top < newStackTop) {
  3576.         PushOTT (&top, securitySize, parameterSize, hashMethod,
  3577.             noOfCounts, noOfBitsPerVerifier,
  3578.             path, authPathValues,
  3579.             rootParameter, countVerifiers,
  3580.             secretKey, SECRET_KEY_SIZE, OTTsize);
  3581.         };
  3582.     WriteBinaryAuxInfo(top, securitySize,
  3583.         noOfCounts, OTTsize, authPathValues, countVerifiers, toggle);
  3584. }
  3585.  
  3586. /*
  3587.  * The following routine creates new signing key/checking key pair and writes
  3588.  * out the new initial aux info and the new public entry.
  3589.  */
  3590. void 
  3591. CreateSignCheckPair (userKeyString, userName, publicDirName, hashMethod,
  3592.     securitySize, parameterSize, noOfBitsPerVerifier, OTTsize)
  3593.     char    *userKeyString;
  3594.     char    *userName;
  3595.     char    *publicDirName;
  3596.     int    hashMethod;
  3597.     int    securitySize;
  3598.     int    parameterSize;
  3599.     int    noOfBitsPerVerifier;
  3600. {    int     i;
  3601.     char    charUserKey[USER_KEY_SIZE_IN_BYTES];
  3602.     word32    userKey[USER_KEY_SIZE];
  3603.     word32    secretKey[SECRET_KEY_SIZE];
  3604.     word32    publicKey[MAX_PUBLIC_KEY_SIZE];
  3605.     word32    hashedUserKey[HASHED_USER_KEY_SIZE];
  3606.  
  3607.     word32    machineKey[MACHINE_KEY_SIZE];
  3608.     int     top;
  3609.     int    newStackTop;
  3610.     word32    authPathValues
  3611.             [MAX_STACK_DEPTH]
  3612.             [2 * MAX_OTT_SIZE]
  3613.             [MAX_SECURITY_SIZE];
  3614.     word32    countVerifiers
  3615.             [MAX_STACK_DEPTH]
  3616.             [MAX_NO_OF_COUNTS]
  3617.             [MAX_SECURITY_SIZE];
  3618.     word32    OTTparameter[MAX_STACK_DEPTH][MAX_PARAMETER_SIZE];
  3619.     word32    path[MAX_STACK_DEPTH];
  3620.     int     noOfCounts;
  3621.     word32    rootParameter[MAX_PARAMETER_SIZE];
  3622.     word32    root[MAX_SECURITY_SIZE];
  3623.     word32    parameter[MAX_PARAMETER_SIZE];
  3624.     FILE    *file1;
  3625.     FILE    *file2;
  3626.     char    file1Name[MAX_FILE_NAME_SIZE_IN_BYTES];
  3627.     char    file2Name[MAX_FILE_NAME_SIZE_IN_BYTES];
  3628.  
  3629.     RangeCheck(securitySize, 2, MAX_SECURITY_SIZE, "Security size");
  3630.     RangeCheck(parameterSize, 2, MAX_PARAMETER_SIZE, "Parameter size");
  3631.     RangeCheck(noOfBitsPerVerifier, 1, MAX_BITS_PER_VERIFIER,
  3632.         "no of bits per verifier");
  3633.     RangeCheck(OTTsize, 4, MAX_OTT_SIZE, "OTT size");
  3634.     if ( ((OTTsize-1) & OTTsize) != 0) {
  3635.         fprintf(stderr, "OTT size is %d, not a power of 2\n",
  3636.             OTTsize);
  3637.         ErrAbort("");
  3638.     };
  3639.     strncpy(charUserKey, userKeyString, USER_KEY_SIZE_IN_BYTES);
  3640.     ConvertBytes (charUserKey, userKey, USER_KEY_SIZE_IN_BYTES);
  3641.     top = 0;
  3642.     noOfCounts = ComputeNumberOfCounts (
  3643.               securitySize, WORD_SIZE_IN_BITS, noOfBitsPerVerifier);
  3644.     /* generate the machine key  */
  3645.     AssignRandom (machineKey, MACHINE_KEY_SIZE, userKey, USER_KEY_SIZE);
  3646. #if DEBUG
  3647.     PrintIt ("machine key is:",
  3648.          machineKey, MACHINE_KEY_SIZE);
  3649.     PrintIt ("user key is:",
  3650.          userKey, USER_KEY_SIZE);
  3651. #endif
  3652.  
  3653.     /* and now we can generate the secret key */
  3654.     HashTwoItems (secretKey, SECRET_KEY_SIZE,
  3655.               machineKey, MACHINE_KEY_SIZE,
  3656.               userKey, USER_KEY_SIZE,
  3657.               hashMethod);
  3658. #if DEBUG
  3659.     PrintIt ("Secret key created is:", secretKey, SECRET_KEY_SIZE);
  3660. #endif
  3661.     /* Generate the random root parameter  */
  3662.     AssignRandom (rootParameter, parameterSize, secretKey, SECRET_KEY_SIZE);
  3663.     /*
  3664.      * The root parameter is now modified to have certain desirable
  3665.      * properties.  The purpose of these modifications is to simplify the
  3666.      * analysis of parameter-parameter collisions (i.e., to make it
  3667.      * simpler to figure out when two parameters are likely to collide --
  3668.      * which can result in a modest reduction in security).  In addition,
  3669.      * when the following modifications are made to the parameter, a
  3670.      * large class of collisions become impossible.  In particular,
  3671.      * collisions between two parameters used with the same secret
  3672.      * signing key are impossible if the number of signed messages is
  3673.      * less than 2**60 or so.
  3674.      * 
  3675.      * The fact that two parameters are guaranteed to be different for two
  3676.      * different locations in the same tree is used to generate different
  3677.      * secret information for different locations in the tree.  Should
  3678.      * the parameters at two different locations in the tree collide, the
  3679.      * result would be a major loss of security.  This is because the
  3680.      * secret signing information is generated deterministically from (a)
  3681.      * the secret key and (b) the parameter value at that point in the
  3682.      * tree.  Thus, should two parameters be identical, the corresponding
  3683.      * secret information for two one-time signatures would be identical,
  3684.      * which is very bad.
  3685.      * 
  3686.      */
  3687.  
  3688.     rootParameter[parameterSize - 1] |= 0x1fL;    /* Bottom 5 bits are:
  3689.                              * 11111  */
  3690.     rootParameter[parameterSize - 1] ^= 0xfL;    /* Bottom 5 bits are:
  3691.                              * 10000  */
  3692.     for (i = WORD_SIZE_IN_BITS * parameterSize - 5; i >= 0; i--)
  3693.         if (FetchBits (rootParameter, parameterSize, i, 4) == 0)
  3694.             SetBit (rootParameter, i);
  3695.  
  3696.     for (i = WORD_SIZE_IN_BITS * parameterSize - 5; i >= 0; i--)
  3697.         if (FetchBits (rootParameter, parameterSize, i, 4) == 0)
  3698.             ErrAbort ("Internal logic error");
  3699.     /* End of diddling the root parameter  */
  3700.  
  3701.     /* initialize the top (i.e. 0th) OTT  */
  3702.     Copy (OTTparameter[top], rootParameter, parameterSize);
  3703.     path[top] = OTTsize;
  3704.     FinishNewOTT (top, securitySize, parameterSize, hashMethod,
  3705.             noOfCounts, noOfBitsPerVerifier, OTTsize,
  3706.             authPathValues, OTTparameter[top], countVerifiers,
  3707.             secretKey, SECRET_KEY_SIZE);
  3708.     Copy (root, authPathValues[top][1], securitySize);
  3709.     newStackTop = ComputeNewStackTop (top, path);
  3710.     Copy (parameter, rootParameter, parameterSize);
  3711.     while (top < newStackTop) {
  3712.         path[top+1] = OTTsize;
  3713.         PushOTT (&top, securitySize, parameterSize, hashMethod,
  3714.             noOfCounts, noOfBitsPerVerifier,
  3715.             path, authPathValues,
  3716.             parameter, countVerifiers,
  3717.             secretKey, SECRET_KEY_SIZE, OTTsize);
  3718.         };
  3719.     /*  generate public key */
  3720.     PackHeader(publicKey, hashMethod, securitySize,
  3721.         parameterSize, noOfBitsPerVerifier);
  3722.     Copy(&publicKey[1], root, securitySize);
  3723.     Copy(&publicKey[1+securitySize], rootParameter, parameterSize);
  3724.     HashTwoItems(hashedUserKey, HASHED_USER_KEY_SIZE,
  3725.         userKey, USER_KEY_SIZE,
  3726.         userKey, USER_KEY_SIZE, hashMethod);
  3727.     for (i=0; i<20; i++) HashTwoItems(
  3728.                 hashedUserKey, HASHED_USER_KEY_SIZE,
  3729.                 hashedUserKey, HASHED_USER_KEY_SIZE,
  3730.                 hashedUserKey, HASHED_USER_KEY_SIZE,
  3731.                 hashMethod);
  3732.     NameStableStorage(file1Name, file2Name);
  3733.     file1 = OpenIfEmpty(file1Name);
  3734.     file2 = OpenIfEmpty(file2Name);
  3735.     WriteStableStorage (file1, file2, machineKey,
  3736.         publicKey, hashedUserKey, path, top, 0, OTTsize);
  3737.     FileSyncAndClose(file1, file1Name);
  3738.     FileSyncAndClose(file2, file2Name);
  3739.     WriteBinaryAuxInfo(top, securitySize,
  3740.         noOfCounts, OTTsize, authPathValues, countVerifiers, 0);
  3741.     WriteEntryToPublicFile (publicDirName, userName,
  3742.                 publicKey, secretKey, SECRET_KEY_SIZE);
  3743.  
  3744. }
  3745.  
  3746. /*
  3747.  * The following routine writes 0's over the old signing key, if
  3748.  * the file exists.
  3749.  */
  3750. void
  3751. DestroyOldKey()
  3752. {    char    file1Name[MAX_FILE_NAME_SIZE_IN_BYTES];
  3753.     char    file2Name[MAX_FILE_NAME_SIZE_IN_BYTES];
  3754.     FILE    *file1;
  3755.     FILE    *file2;
  3756.     char    nothing[WIPE_IT];
  3757.     int    i;
  3758.     int    fileSize;
  3759.  
  3760.     for(i=0; i<WIPE_IT; i++) nothing[i] = (char) 0;
  3761.     NameStableStorage(file1Name, file2Name);
  3762.     if (FileExists(file1Name) != 0)
  3763.         fprintf(stderr, "File \"%s\" does not exist\n", file1Name);
  3764.     else {
  3765.         file1 = fopen(file1Name, "r+");
  3766.         if (file1 == (FILE *) NULL)
  3767.             fprintf(stderr, "Can't open \"%s\" for modify\n",
  3768.                 file1Name);
  3769.         else  {
  3770.             fseek(file1, 0L, 2);
  3771.             fileSize = ftell(file1);
  3772.             if (fileSize < 100) fileSize = 100;
  3773.             if (fileSize > WIPE_IT) fileSize = WIPE_IT;
  3774.             fseek(file1, 0L, 0);
  3775.             if (fwrite(nothing, 1, fileSize, file1) != fileSize)
  3776.                 fprintf(stderr, "Can't write to \"%s\"\n",
  3777.                     file1Name);
  3778.             FileSyncAndClose(file1, file1Name);
  3779.         };
  3780.     };
  3781.     if (FileExists(file2Name) != 0)
  3782.         fprintf(stderr, "File \"%s\" does not exist\n", file2Name);
  3783.     else {
  3784.         file2 = fopen(file2Name, "r+");
  3785.         if (file2 == (FILE *) NULL)
  3786.             fprintf(stderr, "Can't open \"%s\" for modify\n",
  3787.                 file2Name);
  3788.         else {
  3789.             fseek(file2, 0L, 2);
  3790.             fileSize = ftell(file2);
  3791.             if (fileSize < 100) fileSize = 100;
  3792.             if (fileSize > WIPE_IT) fileSize = WIPE_IT;
  3793.             fseek(file2, 0L, 0);
  3794.             if (fwrite(nothing, 1, fileSize, file2) != fileSize)
  3795.                 fprintf(stderr, "Can't write to \"%s\"\n",
  3796.                     file2Name);
  3797.             FileSyncAndClose(file2, file2Name);
  3798.         };
  3799.     };
  3800. }
  3801.  
  3802. /*
  3803.  * given integer hashMethod, determine the proper string name
  3804.  * (printable name) for that hash method.
  3805.  */
  3806. char *
  3807. NameForHashMethod(hashMethod)
  3808.     int    hashMethod;
  3809. {
  3810.     switch (hashMethod) {
  3811.     case SNEFRU4_METHOD:    return("Snefru4");
  3812.     case MD4_METHOD:    return("MD4");
  3813.     default:        return("Unknown");
  3814.  
  3815.     };
  3816. }
  3817.  
  3818.  
  3819. /*
  3820.  * Given a string, s, select the proper integer value for the
  3821.  * hash method specified by the string.
  3822.  * Allowed hash methods are:  SNEFRU4_METHOD and MD4_METHOD.
  3823.  * Other hashing methods can be added in the future as warranted.
  3824.  * Please contact Xerox before selecting a constant for
  3825.  * a new method -- the constant value specifying a given
  3826.  * method should be unique.  Values less than 100 are reserved,
  3827.  * and should not be used except by Xerox.
  3828.  */
  3829. int
  3830. SelectHashMethod(s)
  3831.     char    *s;
  3832. {    if (strcmp(s,"md4"        )==0)    return(MD4_METHOD);
  3833. else if (strcmp(s,"MD4"        )==0)    return(MD4_METHOD);
  3834. else if (strcmp(s,"snefru4"    )==0)    return(SNEFRU4_METHOD);
  3835. else if (strcmp(s,"snefru"    )==0)    return(SNEFRU4_METHOD);
  3836. else if (strcmp(s,"SNEFRU4"    )==0)    return(SNEFRU4_METHOD);
  3837. else if (strcmp(s,"SNEFRU"    )==0)    return(SNEFRU4_METHOD);
  3838. else ErrAbort("Method must be md4 or snefru[4]");
  3839. return(-1);
  3840. };
  3841.  
  3842. /*
  3843.  * The main program reads in a command line, interprets it,
  3844.  * opens the input and signature files (if necessary), and
  3845.  * then invokes the proper routine to sign/check/whatever.
  3846.  */
  3847. void 
  3848. main (argc, argv)
  3849.     int     argc;
  3850.     char   *argv[];
  3851. {    int    j;
  3852.     int    arg;
  3853.     int    start;
  3854.     int    hashMethod;
  3855.     int    securitySize;
  3856.     int    parameterSize;
  3857.     int    noOfBitsPerVerifier;
  3858.     int    OTTsize;
  3859.     char    sigFileName[MAX_FILE_NAME_SIZE_IN_BYTES];
  3860.     int    msgSize;
  3861.     char    *message;
  3862.     char    msgBuffer[MAX_MESSAGE_SIZE_IN_BYTES];
  3863.     FILE    *inputFile;
  3864.     FILE    *sigFile;
  3865.     word32    publicKey[MAX_PUBLIC_KEY_SIZE];
  3866.     char    dateString[80];
  3867.     char    userName[MAX_USER_NAME_SIZE_IN_BYTES];
  3868.     word32    dateTime32;
  3869.     int    exitCode;
  3870.     long    longTemp;
  3871.     int    publicKeySize;
  3872.     int    silentFlag = FALSE;
  3873.     int    verboseFlag = FALSE;
  3874.     char    *publicDirName;
  3875.     int    errorCount;
  3876.     char    commandString[MAX_FILE_NAME_SIZE_IN_BYTES];
  3877.  
  3878.     GetFileSuffix(argv[0], commandString);
  3879.  
  3880.     if (strncmp(commandString,"destroyoldkey", 13)==0) {
  3881.         DestroyOldKey();
  3882.         exit(0);
  3883.     }
  3884.     if (argc<2) {
  3885.         fprintf(stdout, "%s\n", VERSION);
  3886.         fprintf(stdout, "Copyright (C) 1990 Xerox Corporation.\n");
  3887.         fprintf(stdout, "EXPERIMENTAL SOFTWARE\n");
  3888.         fprintf(stdout, "See source code header for scope of\n");
  3889.         fprintf(stdout,
  3890.             "license granted and for warranty disclaimers.\n");
  3891.         fprintf(stderr,
  3892.             "Usage: sign [-m message | -] userKey [files]\n");
  3893.         fprintf(stderr,
  3894.             "   or: check [-dpublicDir] [-s] [-v] [files]\n");
  3895.         fprintf(stderr,
  3896.             "   or: makepublickey [options] userKey user-name\n");
  3897.         fprintf(stderr,
  3898.             "   or: dumpsig [files]\n");
  3899.         fprintf(stderr,
  3900.             "   or: destroyoldkey\n");
  3901.         fprintf(stderr,
  3902.             "   or: recoverauxinfo userKey\n");
  3903.         ErrAbort("");
  3904.     };
  3905.  
  3906.     if (strncmp(commandString,"sign", 4)==0) {
  3907.         fprintf(stdout, "Copyright (C) 1990 Xerox Corporation.\n");
  3908.         fprintf(stdout, "EXPERIMENTAL SOFTWARE\n");
  3909.         fprintf(stdout, "See source code header for scope of\n");
  3910.         fprintf(stdout,
  3911.             "license granted and for warranty disclaimers.\n");
  3912.         if (argc <= 2)
  3913.             ErrAbort(
  3914.                 "Usage: sign [-m message | -] userKey [files]");
  3915.         start = 2;
  3916.         message = "";
  3917.         if (strcmp(argv[1], "-m") == 0) {
  3918.             if (argc <= 3) ErrAbort("No -m message to sign");
  3919.             message = argv[2];
  3920.             start = 4;
  3921.         }
  3922.         else if (strcmp(argv[1], "-") == 0) {
  3923.             msgSize = fread(msgBuffer, 1,
  3924.                 MAX_MESSAGE_SIZE_IN_BYTES, stdin);
  3925.             if (msgSize == MAX_MESSAGE_SIZE_IN_BYTES)
  3926.                 ErrAbort("message from stdin too big");
  3927.             if (ferror(stdin) != 0) {
  3928.                 ErrAbort("Can't read from stdin");
  3929.             };
  3930.             message = msgBuffer;
  3931.             start = 3;
  3932.         }
  3933.         if (argc <= start) 
  3934.             ErrAbort("No files to sign");
  3935.         for(arg=start; arg<argc; arg++) {
  3936.             makeSigFileName(argv[arg], sigFileName);
  3937.             if (SignatureExists(sigFileName) == 0) {
  3938.                 fprintf(stderr,
  3939.                 "\"%s\" already signed.\n", argv[arg]);
  3940.                 continue;
  3941.             };
  3942.             sigFile = fopen(sigFileName, "wb");
  3943.             inputFile = fopen(argv[arg], "rb");
  3944.             if (inputFile == NULL) {
  3945.                 fprintf(stderr,
  3946.                     "Can't open \"%s\" for read\n",
  3947.                     argv[arg]);
  3948.                 continue;
  3949.             };
  3950.             if (sigFile == NULL) {
  3951.                 fprintf(stderr, "Can't open \"%s\" for write\n",
  3952.                     sigFileName);
  3953.                 continue;
  3954.             };
  3955.             Sign (argv[start-1], message, inputFile, sigFile);
  3956.             FileClose(inputFile, argv[arg]);
  3957.             FileClose(sigFile, sigFileName);
  3958.         };
  3959.         exit(0);
  3960.     }
  3961.     else if (strncmp(commandString,"makepublickey", 13)==0) {
  3962.         fprintf(stdout, "Copyright (C) 1990 Xerox Corporation.\n");
  3963.         fprintf(stdout, "EXPERIMENTAL SOFTWARE\n");
  3964.         fprintf(stdout, "See source code header for scope of\n");
  3965.         fprintf(stdout,
  3966.             "license granted and for warranty disclaimers.\n");
  3967.         publicDirName = MAKE_KEY_PUB_DIR_NAME;
  3968.         hashMethod = MD4_METHOD;
  3969.         securitySize = 2;
  3970.         parameterSize = 2;
  3971.         noOfBitsPerVerifier = 4;
  3972.         OTTsize = 32;
  3973.         arg = 1;
  3974.         while (argv[arg][0]=='-') {
  3975.             switch(argv[arg][1]) {
  3976.             case 's':    sscanf(&argv[arg][2],"%d",
  3977.                         &securitySize);
  3978.                     break;
  3979.             case 'p':    sscanf(&argv[arg][2],"%d",
  3980.                         ¶meterSize);
  3981.                     break;
  3982.             case 'b':    sscanf(&argv[arg][2],"%d",
  3983.                         &noOfBitsPerVerifier);
  3984.                     break;
  3985.             case 'n':    sscanf(&argv[arg][2],"%d",
  3986.                         &OTTsize);
  3987.                     break;
  3988.             case 'd':    publicDirName = &argv[arg][2];
  3989.                     break;
  3990.             case 'h':    hashMethod = SelectHashMethod(
  3991.                             &argv[arg][2]);
  3992.                     break;
  3993.             default:    fprintf(stderr,
  3994.                     "Bad arg: \"%s\" ignored.", argv[arg]);
  3995.                     break;
  3996.             };
  3997.             if (++arg == argc) break;
  3998.         };
  3999.         if (arg+2 != argc) {
  4000.             fprintf(stderr,
  4001.             "Usage: makepublickey [options] userKey name\n");
  4002.             fprintf(stderr,
  4003.             "Standard directories are:\n%s\n%s\n%s\n%s\n%s\n",
  4004.                 PUBLIC_DIRECTORY_NAME,
  4005.                 MAKE_KEY_PUB_DIR_NAME,
  4006.                 STABLE1_DIRECTORY,
  4007.                 STABLE2_DIRECTORY,
  4008.                 AUX_INFO_DIRECTORY);
  4009.             ErrAbort("");
  4010.         };
  4011.         fprintf(stderr, "-nUser Name        : \"%s\"\n", argv[arg+1]);
  4012.         fprintf(stderr, "-hhash method      : %s\n",
  4013.             NameForHashMethod(hashMethod));
  4014.         fprintf(stderr, "-ssecurity size    : %d\n", securitySize);
  4015.         fprintf(stderr, "-pparameter size   : %d\n", parameterSize);
  4016.         fprintf(stderr, "-bbits per verifier: %d\n", noOfBitsPerVerifier);
  4017.         fprintf(stderr, "-nOTT size         : %d\n", OTTsize);
  4018.         fprintf(stderr, "-dpublic directory : %s\n", publicDirName);
  4019.         CreateSignCheckPair(argv[arg], argv[arg+1], publicDirName,
  4020.             hashMethod, securitySize,
  4021.             parameterSize, noOfBitsPerVerifier, OTTsize);
  4022.         exit(0);
  4023.     }
  4024.     else if (strncmp(commandString,"check", 5)==0) {
  4025.         publicDirName = PUBLIC_DIRECTORY_NAME;
  4026.         errorCount = 0;
  4027.         for(arg=1; arg<argc; arg++) {
  4028.             if (strcmp(argv[arg], "-s") == 0) {
  4029.                 silentFlag = TRUE;
  4030.                 continue;
  4031.             };
  4032.             if (strcmp(argv[arg], "-v") == 0) {
  4033.                 verboseFlag = TRUE;
  4034.                 continue;
  4035.             };
  4036.             if (strncmp(argv[arg], "-d", 2) == 0) {
  4037.                 publicDirName = &argv[arg][2];
  4038.                 continue;
  4039.             };
  4040.             if (silentFlag != TRUE) {
  4041.                 fprintf(stdout,
  4042.                 "Copyright (C) 1990 Xerox Corporation.\n");
  4043.                 fprintf(stdout,
  4044.                 "EXPERIMENTAL SOFTWARE\n");
  4045.                 fprintf(stdout,
  4046.                 "See source code header for scope of\n");
  4047.                 fprintf(stdout,
  4048.             "license granted and for warranty disclaimers.\n");
  4049.             };
  4050.             makeSigFileName(argv[arg], sigFileName);
  4051.             inputFile = fopen(argv[arg], "rb");
  4052.             sigFile = fopen(sigFileName, "rb");
  4053.             if (inputFile == NULL) {
  4054.                 if (silentFlag != TRUE)
  4055.                     fprintf(stderr,
  4056.                         "Can't open \"%s\" for read\n",
  4057.                         argv[arg]);
  4058.                 errorCount++;
  4059.                 continue;
  4060.             };
  4061.             if (sigFile == NULL) {
  4062.                 if (silentFlag != TRUE)
  4063.                     fprintf(stderr,
  4064.                         "Can't open \"%s\" for read\n",
  4065.                         sigFileName);
  4066.                 FileClose(inputFile, argv[arg]);
  4067.                 errorCount++;
  4068.                 continue;
  4069.             };
  4070.             Check(inputFile, sigFile, publicKey,
  4071.                 &dateTime32, msgBuffer);
  4072.             FileClose(inputFile, argv[arg]);
  4073.             FileClose(sigFile, sigFileName);
  4074.             exitCode = LookUpPublicKey (publicKey,
  4075.                 publicDirName, userName);
  4076.             if (exitCode != 0)
  4077.                 errorCount++;
  4078.             if (silentFlag == TRUE)
  4079.                 continue;
  4080.             if (exitCode == 0) {
  4081.                 longTemp = dateTime32;
  4082.                 strcpy(dateString, ctime(&longTemp));
  4083.                 if (dateString[strlen(dateString)-1] == '\n')
  4084.                     dateString[strlen(dateString)-1] =
  4085.                         (char) 0;
  4086.                 fprintf(stdout,
  4087.                     "\"%s\" signed by \"%s\" on %s.\n",
  4088.                     argv[arg], userName, dateString);
  4089.                 if (    (msgBuffer[0] != 0) &&
  4090.                     (verboseFlag == TRUE))
  4091.                     fprintf(stdout, "Message: \"%s\"\n",
  4092.                         msgBuffer);
  4093.             }
  4094.             else {
  4095.                 fprintf(stdout,
  4096.                 "\"%s\" signature invalid.\n",
  4097.                     argv[arg]);
  4098.                 if (verboseFlag == TRUE) {
  4099.                     fprintf(stdout, "Computed public key=");
  4100.                     publicKeySize =
  4101.                     ComputePublicKeySize(publicKey);
  4102.                     for (j=0; j<publicKeySize; j++)
  4103.                         fprintf(stdout, " %08lx",
  4104.                     publicKey[j]);
  4105.                     fprintf(stdout, "\n");
  4106.                 };
  4107.             };
  4108.         };
  4109.         if (silentFlag != TRUE) {
  4110.             if (errorCount == 0)
  4111.                 fprintf(stderr, "No errors.\n");
  4112.             else
  4113.                 fprintf(stderr, "%d error(s) encountered\n",
  4114.                     errorCount);
  4115.         };
  4116.         exit(errorCount);
  4117.     }
  4118.     else if (strncmp(commandString,"dumpsig", 7)==0) {
  4119.         for(arg=1; arg<argc; arg++) {
  4120.             makeSigFileName(argv[arg], sigFileName);
  4121.             sigFile = fopen(sigFileName, "rb");
  4122.             if (sigFile == (FILE*)NULL)
  4123.                 fprintf(stderr, "Can't open \"%s\" for read\n",
  4124.                     sigFileName);
  4125.             else {
  4126.                 fprintf(stdout,
  4127.                     "Dumping signature file \"%s\"\n",
  4128.                     sigFileName);
  4129.                 DumpSig(sigFile);
  4130.                 FileClose(sigFile, sigFileName);
  4131.             };
  4132.         };
  4133.         exit(0);
  4134.     }
  4135.     else if (strncmp(commandString,"recoverauxinfo", 14)==0) {
  4136.         if (argc != 2)
  4137.             ErrAbort("Usage: recoverauxinfo userKey");
  4138.         RecoverAuxInfo(argv[1]);
  4139.         exit(0);
  4140.     }
  4141.     else
  4142.         ErrAbort("Executable file must be named \"sign\",\
  4143.  \"check\", \"dumpsig\", \"destroyoldkey\",\
  4144.  \"recoverauxinfo\" or \"makepublickey\".");
  4145. }
  4146.